Keep the colleague's microbu-esp32c5 tree in this repository
obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ANY.h"
|
||||
|
||||
asn_OCTET_STRING_specifics_t asn_SPC_ANY_specs = {
|
||||
sizeof(ANY_t),
|
||||
offsetof(ANY_t, _asn_ctx),
|
||||
ASN_OSUBV_ANY
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_ANY = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
OCTET_STRING_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber,
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_hex,
|
||||
ANY_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_hex,
|
||||
ANY_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
ANY_decode_uper,
|
||||
ANY_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
ANY_decode_aper,
|
||||
ANY_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
0, /* Random fill is not defined for ANY type */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ANY = {
|
||||
"ANY",
|
||||
"ANY",
|
||||
&asn_OP_ANY,
|
||||
0, 0, 0, 0,
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
}, /* No constraints */
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_ANY_specs,
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_TYPE_ANY_H
|
||||
#define ASN_TYPE_ANY_H
|
||||
|
||||
#include "OCTET_STRING.h" /* Implemented via OCTET STRING type */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ANY {
|
||||
uint8_t *buf; /* BER-encoded ANY contents */
|
||||
int size; /* Size of the above buffer */
|
||||
|
||||
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
|
||||
} ANY_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ANY;
|
||||
extern asn_TYPE_operation_t asn_OP_ANY;
|
||||
extern asn_OCTET_STRING_specifics_t asn_SPC_ANY_specs;
|
||||
|
||||
#define ANY_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define ANY_print OCTET_STRING_print
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define ANY_compare OCTET_STRING_compare
|
||||
#define ANY_copy OCTET_STRING_copy
|
||||
|
||||
#define ANY_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define ANY_decode_ber OCTET_STRING_decode_ber
|
||||
#define ANY_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define ANY_decode_xer OCTET_STRING_decode_xer_hex
|
||||
xer_type_encoder_f ANY_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f ANY_decode_jer;
|
||||
jer_type_encoder_f ANY_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f ANY_decode_uper;
|
||||
per_type_encoder_f ANY_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f ANY_decode_aper;
|
||||
per_type_encoder_f ANY_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
/******************************
|
||||
* Handy conversion routines. *
|
||||
******************************/
|
||||
|
||||
/* Convert another ASN.1 type into the ANY. This implies DER encoding. */
|
||||
int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr);
|
||||
ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr);
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
int ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr);
|
||||
ANY_t *ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr);
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
/* Convert the contents of the ANY type into the specified type. */
|
||||
int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
int ANY_to_type_aper(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
|
||||
int ANY_to_type_aper_checked(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size))
|
||||
#define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \
|
||||
&asn_DEF_ANY, (buf), (size))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_TYPE_ANY_H */
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ANY.h"
|
||||
#include <errno.h>
|
||||
|
||||
#undef RETURN
|
||||
#define RETURN(_code) \
|
||||
do { \
|
||||
asn_dec_rval_t tmprval; \
|
||||
tmprval.code = _code; \
|
||||
tmprval.consumed = consumed_myself; \
|
||||
return tmprval; \
|
||||
} while(0)
|
||||
|
||||
int
|
||||
ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
|
||||
uint8_t *buffer = NULL;
|
||||
ssize_t erval;
|
||||
|
||||
if(!st || !td) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!sptr) {
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
erval = aper_encode_to_new_buffer(td, td->encoding_constraints.per_constraints, sptr, (void**)&buffer);
|
||||
|
||||
if(erval == -1) {
|
||||
if(buffer) FREEMEM(buffer);
|
||||
return -1;
|
||||
}
|
||||
assert((size_t)erval > 0);
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = buffer;
|
||||
st->size = erval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ANY_t *
|
||||
ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr) {
|
||||
ANY_t tmp;
|
||||
ANY_t *st;
|
||||
|
||||
if(!td || !sptr) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(ANY_fromType_aper(&tmp, td, sptr)) return 0;
|
||||
|
||||
st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
|
||||
if(st) {
|
||||
*st = tmp;
|
||||
return st;
|
||||
} else {
|
||||
FREEMEM(tmp.buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ANY_to_type_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
|
||||
asn_dec_rval_t rval;
|
||||
void *newst = 0;
|
||||
|
||||
if(!st || !td || !struct_ptr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(st->buf == 0) {
|
||||
/* Nothing to convert, make it empty. */
|
||||
*struct_ptr = (void *)0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rval = aper_decode(0, td, (void **)&newst, st->buf, st->size, 0, 0);
|
||||
if(rval.code == RC_OK) {
|
||||
*struct_ptr = newst;
|
||||
return 0;
|
||||
} else {
|
||||
/* Remove possibly partially decoded data. */
|
||||
ASN_STRUCT_FREE(*td, newst);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ANY_to_type_aper_checked(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
|
||||
return ANY_to_type_aper(st, td, struct_ptr) == 0 && *struct_ptr != 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
ANY_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_ANY_specs;
|
||||
size_t consumed_myself = 0;
|
||||
int repeat;
|
||||
ANY_t *st = (ANY_t *)*sptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
|
||||
/*
|
||||
* Allocate the structure.
|
||||
*/
|
||||
if(!st) {
|
||||
st = (ANY_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
ASN_DEBUG("APER Decoding ANY type");
|
||||
|
||||
st->size = 0;
|
||||
do {
|
||||
ssize_t raw_len;
|
||||
ssize_t len_bytes;
|
||||
ssize_t len_bits;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
/* Get the PER length */
|
||||
raw_len = aper_get_length(pd, -1, -1, 0, &repeat);
|
||||
if(raw_len < 0) RETURN(RC_WMORE);
|
||||
if(raw_len == 0 && st->buf) break;
|
||||
|
||||
ASN_DEBUG("Got PER length len %" ASN_PRI_SIZE ", %s (%s)", raw_len,
|
||||
repeat ? "repeat" : "once", td->name);
|
||||
len_bytes = raw_len;
|
||||
len_bits = len_bytes * 8;
|
||||
|
||||
p = REALLOC(st->buf, st->size + len_bytes + 1);
|
||||
if(!p) RETURN(RC_FAIL);
|
||||
st->buf = (uint8_t *)p;
|
||||
|
||||
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
|
||||
if(ret < 0) RETURN(RC_WMORE);
|
||||
consumed_myself += len_bits;
|
||||
st->size += len_bytes;
|
||||
} while(repeat);
|
||||
st->buf[st->size] = 0; /* nul-terminate */
|
||||
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
ANY_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, const void *sptr,
|
||||
asn_per_outp_t *po) {
|
||||
const ANY_t *st = (const ANY_t *)sptr;
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
const uint8_t *buf;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!st || (!st->buf && st->size)) ASN__ENCODE_FAILED;
|
||||
|
||||
buf = st->buf;
|
||||
size = st->size;
|
||||
do {
|
||||
int need_eom = 0;
|
||||
ssize_t may_save = aper_put_length(po, -1, -1, size, &need_eom);
|
||||
if(may_save < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ret = per_put_many_bits(po, buf, may_save * 8);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
|
||||
buf += may_save;
|
||||
size -= may_save;
|
||||
assert(!(may_save & 0x07) || !size);
|
||||
if(need_eom && aper_put_length(po, -1, -1, 0, NULL))
|
||||
ASN__ENCODE_FAILED; /* End of Message length */
|
||||
} while(size);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ANY.h"
|
||||
#include <errno.h>
|
||||
|
||||
struct _callback_arg {
|
||||
uint8_t *buffer;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
|
||||
struct _callback_arg *arg = (struct _callback_arg *)key;
|
||||
|
||||
if((arg->offset + size) >= arg->size) {
|
||||
size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
|
||||
void *p = REALLOC(arg->buffer, nsize);
|
||||
if(!p) return -1;
|
||||
arg->buffer = (uint8_t *)p;
|
||||
arg->size = nsize;
|
||||
}
|
||||
|
||||
memcpy(arg->buffer + arg->offset, buffer, size);
|
||||
arg->offset += size;
|
||||
assert(arg->offset < arg->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
|
||||
struct _callback_arg arg;
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
|
||||
if(!st || !td) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!sptr) {
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg.offset = arg.size = 0;
|
||||
arg.buffer = 0;
|
||||
|
||||
erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
|
||||
if(erval.encoded == -1) {
|
||||
if(arg.buffer) FREEMEM(arg.buffer);
|
||||
return -1;
|
||||
}
|
||||
assert((size_t)erval.encoded == arg.offset);
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = arg.buffer;
|
||||
st->size = arg.offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ANY_t *
|
||||
ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
|
||||
ANY_t tmp;
|
||||
ANY_t *st;
|
||||
|
||||
if(!td || !sptr) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(ANY_fromType(&tmp, td, sptr)) return 0;
|
||||
|
||||
st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
|
||||
if(st) {
|
||||
*st = tmp;
|
||||
return st;
|
||||
} else {
|
||||
FREEMEM(tmp.buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
|
||||
asn_dec_rval_t rval;
|
||||
void *newst = 0;
|
||||
|
||||
if(!st || !td || !struct_ptr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(st->buf == 0) {
|
||||
/* Nothing to convert, make it empty. */
|
||||
*struct_ptr = (void *)0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
|
||||
if(rval.code == RC_OK) {
|
||||
*struct_ptr = newst;
|
||||
return 0;
|
||||
} else {
|
||||
/* Remove possibly partially decoded data. */
|
||||
ASN_STRUCT_FREE(*td, newst);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ANY.h"
|
||||
|
||||
asn_enc_rval_t
|
||||
ANY_encode_jer(const asn_TYPE_descriptor_t *td, const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel,
|
||||
enum jer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
/* Dump as binary */
|
||||
return OCTET_STRING_encode_jer(td, constraints, sptr, ilevel, flags, cb, app_key);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ANY.h"
|
||||
#include <errno.h>
|
||||
|
||||
#undef RETURN
|
||||
#define RETURN(_code) \
|
||||
do { \
|
||||
asn_dec_rval_t tmprval; \
|
||||
tmprval.code = _code; \
|
||||
tmprval.consumed = consumed_myself; \
|
||||
return tmprval; \
|
||||
} while(0)
|
||||
|
||||
asn_dec_rval_t
|
||||
ANY_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_ANY_specs;
|
||||
size_t consumed_myself = 0;
|
||||
int repeat;
|
||||
ANY_t *st = (ANY_t *)*sptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
|
||||
/*
|
||||
* Allocate the structure.
|
||||
*/
|
||||
if(!st) {
|
||||
st = (ANY_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
ASN_DEBUG("UPER Decoding ANY type");
|
||||
|
||||
st->size = 0;
|
||||
do {
|
||||
ssize_t raw_len;
|
||||
ssize_t len_bytes;
|
||||
ssize_t len_bits;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
/* Get the PER length */
|
||||
raw_len = uper_get_length(pd, -1, 0, &repeat);
|
||||
if(raw_len < 0) RETURN(RC_WMORE);
|
||||
if(raw_len == 0 && st->buf) break;
|
||||
|
||||
ASN_DEBUG("Got PER length len %" ASN_PRI_SIZE ", %s (%s)", raw_len,
|
||||
repeat ? "repeat" : "once", td->name);
|
||||
len_bytes = raw_len;
|
||||
len_bits = len_bytes * 8;
|
||||
|
||||
p = REALLOC(st->buf, st->size + len_bytes + 1);
|
||||
if(!p) RETURN(RC_FAIL);
|
||||
st->buf = (uint8_t *)p;
|
||||
|
||||
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
|
||||
if(ret < 0) RETURN(RC_WMORE);
|
||||
consumed_myself += len_bits;
|
||||
st->size += len_bytes;
|
||||
} while(repeat);
|
||||
st->buf[st->size] = 0; /* nul-terminate */
|
||||
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
ANY_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, const void *sptr,
|
||||
asn_per_outp_t *po) {
|
||||
const ANY_t *st = (const ANY_t *)sptr;
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
const uint8_t *buf;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!st || (!st->buf && st->size)) ASN__ENCODE_FAILED;
|
||||
|
||||
buf = st->buf;
|
||||
size = st->size;
|
||||
do {
|
||||
int need_eom = 0;
|
||||
ssize_t may_save = uper_put_length(po, size, &need_eom);
|
||||
if(may_save < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ret = per_put_many_bits(po, buf, may_save * 8);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
|
||||
buf += may_save;
|
||||
size -= may_save;
|
||||
assert(!(may_save & 0x07) || !size);
|
||||
if(need_eom && uper_put_length(po, 0, 0))
|
||||
ASN__ENCODE_FAILED; /* End of Message length */
|
||||
} while(size);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ANY.h"
|
||||
|
||||
asn_enc_rval_t
|
||||
ANY_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
if(flags & XER_F_CANONICAL) {
|
||||
/*
|
||||
* Canonical XER-encoding of ANY type is not supported.
|
||||
*/
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/* Dump as binary */
|
||||
return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
|
||||
/*
|
||||
* BIT STRING basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
|
||||
};
|
||||
asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs = {
|
||||
sizeof(BIT_STRING_t),
|
||||
offsetof(BIT_STRING_t, _asn_ctx),
|
||||
ASN_OSUBV_BIT
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_BIT_STRING = {
|
||||
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
BIT_STRING_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
BIT_STRING_compare,
|
||||
BIT_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_binary,
|
||||
BIT_STRING_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
BIT_STRING_decode_jer,
|
||||
BIT_STRING_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
BIT_STRING_decode_oer,
|
||||
BIT_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
BIT_STRING_decode_uper, /* Unaligned PER decoder */
|
||||
BIT_STRING_encode_uper, /* Unaligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper, /* Aligned PER decoder */
|
||||
OCTET_STRING_encode_aper, /* Aligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
BIT_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
|
||||
"BIT STRING",
|
||||
"BIT_STRING",
|
||||
&asn_OP_BIT_STRING,
|
||||
asn_DEF_BIT_STRING_tags,
|
||||
sizeof(asn_DEF_BIT_STRING_tags)
|
||||
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
|
||||
asn_DEF_BIT_STRING_tags, /* Same as above */
|
||||
sizeof(asn_DEF_BIT_STRING_tags)
|
||||
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
BIT_STRING_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_BIT_STRING_specs
|
||||
};
|
||||
|
||||
/*
|
||||
* BIT STRING generic constraint.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
|
||||
if(st && st->buf) {
|
||||
if((st->size == 0 && st->bits_unused)
|
||||
|| st->bits_unused < 0 || st->bits_unused > 7) {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: invalid padding byte (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: value not given (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-destructively remove the trailing 0-bits from the given bit string.
|
||||
*/
|
||||
const BIT_STRING_t *
|
||||
BIT_STRING__compactify(const BIT_STRING_t *st, BIT_STRING_t *tmp) {
|
||||
const uint8_t *b;
|
||||
union {
|
||||
const uint8_t *c_buf;
|
||||
uint8_t *nc_buf;
|
||||
} unconst;
|
||||
|
||||
if(st->size == 0) {
|
||||
assert(st->bits_unused == 0);
|
||||
return st;
|
||||
} else {
|
||||
for(b = &st->buf[st->size - 1]; b > st->buf && *b == 0; b--) {
|
||||
;
|
||||
}
|
||||
/* b points to the last byte which may contain data */
|
||||
if(*b) {
|
||||
int unused = 7;
|
||||
uint8_t v = *b;
|
||||
v &= -(int8_t)v;
|
||||
if(v & 0x0F) unused -= 4;
|
||||
if(v & 0x33) unused -= 2;
|
||||
if(v & 0x55) unused -= 1;
|
||||
tmp->size = b-st->buf + 1;
|
||||
tmp->bits_unused = unused;
|
||||
} else {
|
||||
tmp->size = b-st->buf;
|
||||
tmp->bits_unused = 0;
|
||||
}
|
||||
|
||||
assert(b >= st->buf);
|
||||
}
|
||||
|
||||
unconst.c_buf = st->buf;
|
||||
tmp->buf = unconst.nc_buf;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lexicographically compare the common prefix of both strings,
|
||||
* and if it is the same return -1 for the smallest string.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
|
||||
const void *bptr) {
|
||||
/*
|
||||
* Remove information about trailing bits, since
|
||||
* X.680 (08/2015) #22.7 "ensure that different semantics are not"
|
||||
* "associated with [values that differ only in] the trailing 0 bits."
|
||||
*/
|
||||
BIT_STRING_t compact_a, compact_b;
|
||||
const BIT_STRING_t *a = BIT_STRING__compactify(aptr, &compact_a);
|
||||
const BIT_STRING_t *b = BIT_STRING__compactify(bptr, &compact_b);
|
||||
const asn_OCTET_STRING_specifics_t *specs = td->specifics;
|
||||
|
||||
(void)specs;
|
||||
assert(specs && specs->subvariant == ASN_OSUBV_BIT);
|
||||
|
||||
if(a && b) {
|
||||
size_t common_prefix_size = a->size <= b->size ? a->size : b->size;
|
||||
int ret = memcmp(a->buf, b->buf, common_prefix_size);
|
||||
if(ret == 0) {
|
||||
/* Figure out which string with equal prefixes is longer. */
|
||||
if(a->size < b->size) {
|
||||
return -1;
|
||||
} else if(a->size > b->size) {
|
||||
return 1;
|
||||
} else {
|
||||
/* Figure out how many unused bits */
|
||||
if(a->bits_unused > b->bits_unused) {
|
||||
return -1;
|
||||
} else if(a->bits_unused < b->bits_unused) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
} else if(!a && !b) {
|
||||
return 0;
|
||||
} else if(!a) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
BIT_STRING_copy(const asn_TYPE_descriptor_t *td, void **aptr,
|
||||
const void *bptr) {
|
||||
const asn_OCTET_STRING_specifics_t *specs = td->specifics;
|
||||
BIT_STRING_t *a = (BIT_STRING_t *)*aptr;
|
||||
const BIT_STRING_t *b = (const BIT_STRING_t *)bptr;
|
||||
|
||||
if(!b) {
|
||||
if(a) {
|
||||
FREEMEM(a->buf);
|
||||
FREEMEM(a);
|
||||
*aptr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!a) {
|
||||
a = *aptr = CALLOC(1, specs->struct_size);
|
||||
if(!a) return -1;
|
||||
}
|
||||
|
||||
uint8_t* buf = MALLOC(b->size + 1);
|
||||
if(!buf) return -1;
|
||||
memcpy(buf, b->buf, b->size);
|
||||
buf[b->size] = 0;
|
||||
|
||||
FREEMEM(a->buf);
|
||||
a->buf = buf;
|
||||
a->size = b->size;
|
||||
a->bits_unused = b->bits_unused;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BIT_STRING_H_
|
||||
#define _BIT_STRING_H_
|
||||
|
||||
#include "OCTET_STRING.h" /* Some help from OCTET STRING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct BIT_STRING_s {
|
||||
uint8_t *buf; /* BIT STRING body */
|
||||
size_t size; /* Size of the above buffer */
|
||||
|
||||
int bits_unused;/* Unused trailing bits in the last octet (0..7) */
|
||||
|
||||
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
|
||||
} BIT_STRING_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
|
||||
extern asn_TYPE_operation_t asn_OP_BIT_STRING;
|
||||
extern asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs;
|
||||
|
||||
#define BIT_STRING_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f BIT_STRING_print; /* Human-readable output */
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f BIT_STRING_compare;
|
||||
asn_struct_copy_f BIT_STRING_copy;
|
||||
|
||||
asn_constr_check_f BIT_STRING_constraint;
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define BIT_STRING_decode_ber OCTET_STRING_decode_ber
|
||||
#define BIT_STRING_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define BIT_STRING_decode_xer OCTET_STRING_decode_xer_binary
|
||||
xer_type_encoder_f BIT_STRING_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f BIT_STRING_decode_jer;
|
||||
jer_type_encoder_f BIT_STRING_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f BIT_STRING_decode_oer;
|
||||
oer_type_encoder_f BIT_STRING_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f BIT_STRING_decode_uper;
|
||||
per_type_encoder_f BIT_STRING_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define BIT_STRING_decode_aper OCTET_STRING_decode_aper
|
||||
#define BIT_STRING_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f BIT_STRING_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
const BIT_STRING_t *BIT_STRING__compactify(const BIT_STRING_t *st, BIT_STRING_t *tmp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BIT_STRING_H_ */
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_application.h"
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel,
|
||||
enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
const char * const h2c = "0123456789ABCDEF";
|
||||
char scratch[16 * 3 + 4];
|
||||
char *p = scratch;
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
const asn_jer_constraints_t* cts = constraints ?
|
||||
constraints : td->encoding_constraints.jer_constraints;
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
int jmin = flags & JER_F_MINIFIED;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
buf = st->buf;
|
||||
end = buf + st->size - 1; /* Last byte is special */
|
||||
|
||||
/*
|
||||
* Hex dump
|
||||
*/
|
||||
if(cts && cts->size != -1) { /* Fixed size */
|
||||
*p++ = '"';
|
||||
for(int i = 0; buf < end; buf++, i++) {
|
||||
if(!(i % 16) && (i || st->size > 16)) {
|
||||
ASN__CALLBACK(scratch, p-scratch);
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = h2c[*buf >> 4];
|
||||
*p++ = h2c[*buf & 0x0F];
|
||||
}
|
||||
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
|
||||
if(buf == end) {
|
||||
int ubits = st->bits_unused;
|
||||
uint8_t v = *buf & (0xff << ubits);
|
||||
*p++ = h2c[v >> 4];
|
||||
*p++ = h2c[v & 0x0F];
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = '"';
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
} else { /* Variable size */
|
||||
ASN__CALLBACK("{", 1);
|
||||
if(!jmin) {
|
||||
ASN__TEXT_INDENT(1, ilevel + 1);
|
||||
ASN__CALLBACK("\"value\": ", 9);
|
||||
} else {
|
||||
ASN__CALLBACK("\"value\":", 8);
|
||||
}
|
||||
*p++ = '"';
|
||||
for(int i = 0; buf < end; buf++, i++) {
|
||||
if(!(i % 16) && (i || st->size > 16)) {
|
||||
ASN__CALLBACK(scratch, p-scratch);
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = h2c[*buf >> 4];
|
||||
*p++ = h2c[*buf & 0x0F];
|
||||
}
|
||||
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
|
||||
if(buf == end) {
|
||||
int ubits = st->bits_unused;
|
||||
uint8_t v = *buf & (0xff << ubits);
|
||||
*p++ = h2c[v >> 4];
|
||||
*p++ = h2c[v & 0x0F];
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = '"';
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
|
||||
ASN__CALLBACK(",", 1);
|
||||
if (!jmin) {
|
||||
ASN__TEXT_INDENT(1, ilevel + 1);
|
||||
}
|
||||
|
||||
if(!jmin) {
|
||||
ASN__CALLBACK("\"length\": ", 10);
|
||||
} else {
|
||||
ASN__CALLBACK("\"length\":", 9);
|
||||
}
|
||||
int wr = snprintf(scratch, sizeof(scratch), "%zu",
|
||||
st->size * 8 - (st->bits_unused));
|
||||
if(wr < 0 || (size_t)wr >= sizeof(scratch)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__CALLBACK(scratch, wr);
|
||||
if (!jmin) {
|
||||
ASN__TEXT_INDENT(1, ilevel);
|
||||
}
|
||||
ASN__CALLBACK("}", 1);
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a standardized complex structure.
|
||||
*/
|
||||
#undef RETURN
|
||||
#define RETURN(_code) \
|
||||
do { \
|
||||
rval.code = _code; \
|
||||
rval.consumed = consumed_myself; \
|
||||
return rval; \
|
||||
} while(0)
|
||||
|
||||
#define SKIPCHAR(_c) \
|
||||
do { \
|
||||
int found = 0; \
|
||||
for (; p < pend; ++p) { \
|
||||
if (*p == _c) { \
|
||||
found = 1; ++p; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if(!found) RETURN(RC_WMORE); \
|
||||
} while(0)
|
||||
|
||||
asn_dec_rval_t
|
||||
BIT_STRING_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
void **sptr,
|
||||
const void *buf_ptr, size_t size) {
|
||||
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
|
||||
const asn_jer_constraints_t *cts = constraints ?
|
||||
constraints : td->encoding_constraints.jer_constraints;
|
||||
asn_dec_rval_t rval; /* Return value from the decoder */
|
||||
ssize_t consumed_myself = 0; /* Consumed bytes from buf_ptr */
|
||||
|
||||
/*
|
||||
* Create the string if does not exist.
|
||||
*/
|
||||
if(!st) {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
const char *p = (const char*)buf_ptr;
|
||||
const char *pend = p + size;
|
||||
|
||||
if(!cts || cts->size == -1) {
|
||||
SKIPCHAR('{');
|
||||
SKIPCHAR('"');
|
||||
if(pend-p < 5) RETURN(RC_WMORE);
|
||||
if(0 != memcmp(p, "value", 5)) RETURN(RC_FAIL);
|
||||
p += 5;
|
||||
SKIPCHAR('"');
|
||||
SKIPCHAR(':');
|
||||
}
|
||||
|
||||
/* bitstring value */
|
||||
SKIPCHAR('"');
|
||||
|
||||
/* calculate size */
|
||||
const char* p0 = p;
|
||||
SKIPCHAR('"');
|
||||
const char* p1 = p - 1;
|
||||
p = p0;
|
||||
|
||||
void *nptr = REALLOC(st->buf, (p1-p0 + 1) / 2 + 1);
|
||||
if(!nptr) RETURN(RC_FAIL);
|
||||
st->buf = (uint8_t *)nptr;
|
||||
uint8_t *buf = st->buf;
|
||||
unsigned int clv = 0;
|
||||
int half = 0;
|
||||
|
||||
for(; p < p1; p++) {
|
||||
int ch = *(const unsigned char *)p;
|
||||
switch(ch) {
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
|
||||
clv = (clv << 4) + (ch - 0x30);
|
||||
break;
|
||||
case 0x41: case 0x42: case 0x43: /* ABC */
|
||||
case 0x44: case 0x45: case 0x46: /* DEF */
|
||||
clv = (clv << 4) + (ch - 0x41 + 10);
|
||||
break;
|
||||
case 0x61: case 0x62: case 0x63: /* abc */
|
||||
case 0x64: case 0x65: case 0x66: /* def */
|
||||
clv = (clv << 4) + (ch - 0x61 + 10);
|
||||
break;
|
||||
default:
|
||||
*buf = 0; /* JIC */
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
if(half++) {
|
||||
half = 0;
|
||||
*buf++ = clv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check partial decoding.
|
||||
*/
|
||||
if(half) {
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
st->size = buf - st->buf; /* Adjust the buffer size */
|
||||
st->buf[st->size] = 0; /* Courtesy termination */
|
||||
|
||||
SKIPCHAR('"');
|
||||
|
||||
if(!cts || cts->size == -1) {
|
||||
SKIPCHAR(',');
|
||||
SKIPCHAR('"');
|
||||
if(pend-p < 6) RETURN(RC_WMORE);
|
||||
if(0 != memcmp(p, "length", 6)) RETURN(RC_FAIL);
|
||||
p += 6;
|
||||
SKIPCHAR('"');
|
||||
SKIPCHAR(':');
|
||||
p0 = p;
|
||||
/* Skip whitespace, numbers, for length calc for INTEGER dec
|
||||
* Stop on first non-whitespace/non-number */
|
||||
int numbered = 0;
|
||||
for (; p < pend; ++p) {
|
||||
switch (*p) {
|
||||
case 0x09: case 0x0a: case 0x0c: case 0x0d:
|
||||
case 0x20:
|
||||
if(!numbered) continue;
|
||||
else break;
|
||||
/* Ignore whitespace */
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
|
||||
case 0x2d: /*-*/
|
||||
numbered = 1;
|
||||
continue;
|
||||
}
|
||||
if(numbered) break;
|
||||
}
|
||||
if(!numbered) RETURN(RC_FAIL);
|
||||
|
||||
unsigned long length;
|
||||
|
||||
INTEGER_t integer = { 0 };
|
||||
void *integer_ptr = (void *)&integer;
|
||||
memset(&integer, 0, sizeof(integer));
|
||||
|
||||
asn_dec_rval_t dec =
|
||||
INTEGER_decode_jer(NULL, &asn_DEF_INTEGER, NULL, &integer_ptr, p0, p-p0);
|
||||
if(dec.code == RC_OK) {
|
||||
if(asn_INTEGER2ulong(&integer, (unsigned long *)&length)) {
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
} else {
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &integer);
|
||||
|
||||
if(dec.code != RC_OK) RETURN(RC_FAIL);
|
||||
st->bits_unused = (st->size * 8) - length;
|
||||
|
||||
SKIPCHAR('}');
|
||||
} else {
|
||||
if(st->size * 8 < (size_t)cts->size) {
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
st->bits_unused = (st->size * 8) - cts->size;
|
||||
}
|
||||
|
||||
consumed_myself = (const char *)p - (const char *)buf_ptr;
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
BIT_STRING_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
|
||||
const asn_oer_constraints_t *cts =
|
||||
constraints ? constraints : td->encoding_constraints.oer_constraints;
|
||||
ssize_t ct_size = cts ? cts->size : -1;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
size_t expected_length = 0;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(!st) {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct_size >= 0) {
|
||||
expected_length = (ct_size + 7) >> 3;
|
||||
st->bits_unused = (8 - (ct_size & 7)) & 7;
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #13.3.1
|
||||
* Encode length determinant as _number of octets_, but only
|
||||
* if upper bound is not equal to lower bound.
|
||||
*/
|
||||
ssize_t len_len = oer_fetch_length(ptr, size, &expected_length);
|
||||
if(len_len > 0) {
|
||||
ptr = (const char *)ptr + len_len;
|
||||
size -= len_len;
|
||||
} else if(len_len == 0) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else if(len_len < 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(expected_length < 1) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else if(expected_length > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
st->bits_unused = ((const uint8_t *)ptr)[0];
|
||||
if(st->bits_unused & ~7) {
|
||||
ASN_DEBUG("%s: unused bits outside of 0..7 range", td->name);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
ptr = (const char *)ptr + 1;
|
||||
size--;
|
||||
expected_length--;
|
||||
rval.consumed = len_len + 1;
|
||||
}
|
||||
|
||||
if(size < expected_length) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else {
|
||||
uint8_t *buf = MALLOC(expected_length + 1);
|
||||
if(buf == NULL) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
memcpy(buf, ptr, expected_length);
|
||||
buf[expected_length] = '\0';
|
||||
}
|
||||
FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = expected_length;
|
||||
if(expected_length > 0) {
|
||||
buf[expected_length - 1] &= (0xff << st->bits_unused);
|
||||
}
|
||||
|
||||
rval.consumed += expected_length;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
asn_enc_rval_t erval = {0, 0, 0};
|
||||
const asn_oer_constraints_t *cts =
|
||||
constraints ? constraints : td->encoding_constraints.oer_constraints;
|
||||
ssize_t ct_size = cts ? cts->size : -1;
|
||||
size_t trailing_zeros = 0;
|
||||
int fix_last_byte = 0;
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
if(st->bits_unused & ~7) {
|
||||
ASN_DEBUG("BIT STRING unused bits %d out of 0..7 range",
|
||||
st->bits_unused);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
if(st->bits_unused && !(st->size && st->buf)) {
|
||||
ASN_DEBUG("BIT STRING %s size 0 can't support unused bits %d", td->name,
|
||||
st->bits_unused);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct_size >= 0) {
|
||||
size_t ct_bytes = (ct_size + 7) >> 3;
|
||||
if(st->size > ct_bytes) {
|
||||
ASN_DEBUG("More bits in BIT STRING %s (%" ASN_PRI_SSIZE ") than constrained %" ASN_PRI_SSIZE "",
|
||||
td->name, 8 * st->size - st->bits_unused, ct_size);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
trailing_zeros = ct_bytes - st->size; /* Allow larger constraint */
|
||||
} else {
|
||||
uint8_t ub = st->bits_unused & 7;
|
||||
ssize_t len_len = oer_serialize_length(1 + st->size, cb, app_key);
|
||||
if(len_len < 0) ASN__ENCODE_FAILED;
|
||||
if(cb(&ub, 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
erval.encoded += len_len + 1;
|
||||
}
|
||||
|
||||
if(st->bits_unused) {
|
||||
if(st->buf[st->size - 1] & (0xff << st->bits_unused)) {
|
||||
fix_last_byte = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(cb(st->buf, st->size - fix_last_byte, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(fix_last_byte) {
|
||||
uint8_t b = st->buf[st->size - 1] & (0xff << st->bits_unused);
|
||||
if(cb(&b, 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
erval.encoded += st->size;
|
||||
|
||||
if(trailing_zeros) {
|
||||
static uint8_t zeros[16];
|
||||
while(trailing_zeros > 0) {
|
||||
int ret;
|
||||
if(trailing_zeros < sizeof(zeros)) {
|
||||
ret = cb(zeros, trailing_zeros, app_key);
|
||||
erval.encoded += trailing_zeros;
|
||||
} else {
|
||||
ret = cb(zeros, sizeof(zeros), app_key);
|
||||
erval.encoded += sizeof(zeros);
|
||||
}
|
||||
if(ret < 0) ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return erval;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
|
||||
/*
|
||||
* BIT STRING specific contents printer.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const char * const h2c = "0123456789ABCDEF";
|
||||
char scratch[64];
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
char *p = scratch;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
|
||||
if(!st || !st->buf)
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
|
||||
ilevel++;
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
|
||||
/*
|
||||
* Hexadecimal dump.
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
if((buf - st->buf) % 16 == 0 && (st->size > 16)
|
||||
&& buf != st->buf) {
|
||||
_i_INDENT(1);
|
||||
/* Dump the string */
|
||||
if(cb(scratch, p - scratch, app_key) < 0) return -1;
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = h2c[*buf >> 4];
|
||||
*p++ = h2c[*buf & 0x0F];
|
||||
*p++ = 0x20;
|
||||
}
|
||||
|
||||
if(p > scratch) {
|
||||
p--; /* Eat the tailing space */
|
||||
|
||||
if((st->size > 16)) {
|
||||
_i_INDENT(1);
|
||||
}
|
||||
|
||||
/* Dump the incomplete 16-bytes row */
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(st->bits_unused) {
|
||||
int ret = snprintf(scratch, sizeof(scratch), " (%d bit%s unused)",
|
||||
st->bits_unused, st->bits_unused == 1 ? "" : "s");
|
||||
assert(ret > 0 && ret < (ssize_t)sizeof(scratch));
|
||||
if(ret > 0 && ret < (ssize_t)sizeof(scratch)
|
||||
&& cb(scratch, ret, app_key) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
|
||||
asn_random_fill_result_t
|
||||
BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_BIT_STRING_specs;
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
static unsigned lengths[] = {0, 1, 2, 3, 4, 8,
|
||||
126, 127, 128, 16383, 16384, 16385,
|
||||
65534, 65535, 65536, 65537};
|
||||
uint8_t *buf;
|
||||
uint8_t *bend;
|
||||
uint8_t *b;
|
||||
size_t rnd_bits, rnd_len;
|
||||
BIT_STRING_t *st;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
switch(specs->subvariant) {
|
||||
case ASN_OSUBV_ANY:
|
||||
return result_failed;
|
||||
case ASN_OSUBV_BIT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Figure out how far we should go */
|
||||
rnd_bits = lengths[asn_random_between(
|
||||
0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
if(!constraints || !constraints->per_constraints)
|
||||
constraints = &td->encoding_constraints;
|
||||
if(constraints->per_constraints) {
|
||||
const asn_per_constraint_t *pc = &constraints->per_constraints->size;
|
||||
if(pc->flags & APC_CONSTRAINED) {
|
||||
long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
|
||||
? pc->upper_bound
|
||||
: (ssize_t)max_length;
|
||||
if(max_length < (size_t)pc->lower_bound) {
|
||||
return result_skipped;
|
||||
}
|
||||
if(pc->flags & APC_EXTENSIBLE) {
|
||||
switch(asn_random_between(0, 5)) {
|
||||
case 0:
|
||||
if(pc->lower_bound > 0) {
|
||||
rnd_bits = pc->lower_bound - 1;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case 1:
|
||||
rnd_bits = pc->upper_bound + 1;
|
||||
break;
|
||||
case 2:
|
||||
/* Keep rnd_bits from the table */
|
||||
if(rnd_bits < max_length) {
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
rnd_bits = asn_random_between(pc->lower_bound,
|
||||
suggested_upper_bound);
|
||||
}
|
||||
} else {
|
||||
rnd_bits =
|
||||
asn_random_between(pc->lower_bound, suggested_upper_bound);
|
||||
}
|
||||
} else {
|
||||
rnd_bits = asn_random_between(0, max_length - 1);
|
||||
}
|
||||
} else {
|
||||
#else
|
||||
if(!constraints) constraints = &td->encoding_constraints;
|
||||
{
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
if(rnd_bits >= max_length) {
|
||||
rnd_bits = asn_random_between(0, max_length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
rnd_len = (rnd_bits + 7) / 8;
|
||||
buf = CALLOC(1, rnd_len + 1);
|
||||
if(!buf) return result_failed;
|
||||
|
||||
bend = &buf[rnd_len];
|
||||
|
||||
for(b = buf; b < bend; b++) {
|
||||
*(uint8_t *)b = asn_random_between(0, 255);
|
||||
}
|
||||
*b = 0; /* Zero-terminate just in case. */
|
||||
|
||||
if(*sptr) {
|
||||
st = *sptr;
|
||||
FREEMEM(st->buf);
|
||||
} else {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) {
|
||||
FREEMEM(buf);
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
st->buf = buf;
|
||||
st->size = rnd_len;
|
||||
st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7;
|
||||
if(st->bits_unused) {
|
||||
assert(st->size > 0);
|
||||
st->buf[st->size-1] &= 0xff << st->bits_unused;
|
||||
}
|
||||
|
||||
result_ok.length = st->size;
|
||||
return result_ok;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
|
||||
#undef RETURN
|
||||
#define RETURN(_code) \
|
||||
do { \
|
||||
asn_dec_rval_t tmprval; \
|
||||
tmprval.code = _code; \
|
||||
tmprval.consumed = consumed_myself; \
|
||||
return tmprval; \
|
||||
} while(0)
|
||||
|
||||
static asn_per_constraint_t asn_DEF_BIT_STRING_constraint_size = {
|
||||
APC_SEMI_CONSTRAINED, -1, -1, 0, 0};
|
||||
|
||||
asn_dec_rval_t
|
||||
BIT_STRING_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_OCTET_STRING_specifics_t *specs = td->specifics
|
||||
? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_BIT_STRING_specs;
|
||||
const asn_per_constraints_t *pc =
|
||||
constraints ? constraints : td->encoding_constraints.per_constraints;
|
||||
const asn_per_constraint_t *csiz;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
|
||||
ssize_t consumed_myself = 0;
|
||||
int repeat;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(pc) {
|
||||
csiz = &pc->size;
|
||||
} else {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
}
|
||||
|
||||
if(specs->subvariant != ASN_OSUBV_BIT) {
|
||||
ASN_DEBUG("Subvariant %d is not BIT OSUBV_BIT", specs->subvariant);
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the string.
|
||||
*/
|
||||
if(!st) {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
ASN_DEBUG("PER Decoding %s size %"ASN_PRIdMAX" .. %"ASN_PRIdMAX" bits %d",
|
||||
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
|
||||
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
|
||||
|
||||
if(csiz->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) RETURN(RC_WMORE);
|
||||
if(inext) {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
}
|
||||
}
|
||||
|
||||
if(csiz->effective_bits >= 0) {
|
||||
FREEMEM(st->buf);
|
||||
st->size = (csiz->upper_bound + 7) >> 3;
|
||||
st->buf = (uint8_t *)MALLOC(st->size + 1);
|
||||
if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
|
||||
}
|
||||
|
||||
/* X.691, #16.5: zero-length encoding */
|
||||
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
|
||||
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
|
||||
if(csiz->effective_bits == 0) {
|
||||
int ret;
|
||||
ASN_DEBUG("Encoding BIT STRING size %"ASN_PRIdMAX"", csiz->upper_bound);
|
||||
ret = per_get_many_bits(pd, st->buf, 0, csiz->upper_bound);
|
||||
if(ret < 0) RETURN(RC_WMORE);
|
||||
consumed_myself += csiz->upper_bound;
|
||||
st->buf[st->size] = 0;
|
||||
st->bits_unused = (8 - (csiz->upper_bound & 0x7)) & 0x7;
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
|
||||
st->size = 0;
|
||||
do {
|
||||
ssize_t raw_len;
|
||||
ssize_t len_bytes;
|
||||
ssize_t len_bits;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
/* Get the PER length */
|
||||
raw_len = uper_get_length(pd, csiz->effective_bits, csiz->lower_bound,
|
||||
&repeat);
|
||||
if(raw_len < 0) RETURN(RC_WMORE);
|
||||
if(raw_len == 0 && st->buf) break;
|
||||
/* Check upper bound for Constrained Length */
|
||||
if (csiz->effective_bits >= 0 && csiz->effective_bits <= 16 && raw_len > csiz->upper_bound && !(csiz->flags & APC_EXTENSIBLE)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
|
||||
(long)csiz->effective_bits, (long)raw_len,
|
||||
repeat ? "repeat" : "once", td->name);
|
||||
len_bits = raw_len;
|
||||
len_bytes = (len_bits + 7) >> 3;
|
||||
if(len_bits & 0x7) st->bits_unused = 8 - (len_bits & 0x7);
|
||||
/* len_bits be multiple of 16K if repeat is set */
|
||||
p = REALLOC(st->buf, st->size + len_bytes + 1);
|
||||
if(!p) RETURN(RC_FAIL);
|
||||
st->buf = (uint8_t *)p;
|
||||
|
||||
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
|
||||
if(ret < 0) RETURN(RC_WMORE);
|
||||
st->size += len_bytes;
|
||||
} while(repeat);
|
||||
st->buf[st->size] = 0; /* nul-terminate */
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_BIT_STRING_specs;
|
||||
const asn_per_constraints_t *pc =
|
||||
constraints ? constraints : td->encoding_constraints.per_constraints;
|
||||
const asn_per_constraint_t *csiz;
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
#if defined(UPER_REMOVE_TRAILING_BITS)
|
||||
BIT_STRING_t compact_bstr; /* Do not modify this directly! */
|
||||
#endif
|
||||
asn_enc_rval_t er = { 0, 0, 0 };
|
||||
int inext = 0; /* Lies not within extension root */
|
||||
size_t size_in_bits;
|
||||
const uint8_t *buf;
|
||||
int ret;
|
||||
int ct_extensible;
|
||||
|
||||
if(!st || (!st->buf && st->size))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
if(specs->subvariant == ASN_OSUBV_BIT) {
|
||||
if((st->size == 0 && st->bits_unused) || (st->bits_unused & ~7))
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(pc) {
|
||||
csiz = &pc->size;
|
||||
} else {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
}
|
||||
ct_extensible = csiz->flags & APC_EXTENSIBLE;
|
||||
|
||||
#if defined(UPER_REMOVE_TRAILING_BITS)
|
||||
/* Figure out the size without the trailing bits */
|
||||
st = BIT_STRING__compactify(st, &compact_bstr);
|
||||
/*
|
||||
* Reason for disabling the above truncation:
|
||||
* trailing bits in a bit-string usually
|
||||
* are meaningful, as "0000" is not the same as "000000".
|
||||
*/
|
||||
#endif /* UPER_REMOVE_TRAILING_BITS */
|
||||
size_in_bits = 8 * st->size - st->bits_unused;
|
||||
|
||||
ASN_DEBUG(
|
||||
"Encoding %s into %" ASN_PRI_SIZE " bits"
|
||||
" (%"ASN_PRIdMAX"..%"ASN_PRIdMAX", effective %d)%s",
|
||||
td->name, size_in_bits, csiz->lower_bound, csiz->upper_bound,
|
||||
csiz->effective_bits, ct_extensible ? " EXT" : "");
|
||||
|
||||
/* Figure out whether size lies within PER visible constraint */
|
||||
|
||||
if(csiz->effective_bits >= 0) {
|
||||
if((ssize_t)size_in_bits > csiz->upper_bound) {
|
||||
if(ct_extensible) {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
inext = 1;
|
||||
} else {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inext = 0;
|
||||
}
|
||||
|
||||
if(ct_extensible) {
|
||||
/* Declare whether length is [not] within extension root */
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(csiz->effective_bits >= 0 && !inext) {
|
||||
int add_trailer = (ssize_t)size_in_bits < csiz->lower_bound;
|
||||
ASN_DEBUG(
|
||||
"Encoding %" ASN_PRI_SIZE " bytes (%"ASN_PRIdMAX"), length (in %d bits) trailer %d; actual "
|
||||
"value %" ASN_PRI_SSIZE "",
|
||||
st->size, size_in_bits - csiz->lower_bound, csiz->effective_bits,
|
||||
add_trailer,
|
||||
add_trailer ? 0 : (ssize_t)size_in_bits - (ssize_t)csiz->lower_bound);
|
||||
ret = per_put_few_bits(
|
||||
po, add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound,
|
||||
csiz->effective_bits);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
ret = per_put_many_bits(po, st->buf, size_in_bits);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
if(add_trailer) {
|
||||
static const uint8_t zeros[16];
|
||||
size_t trailing_zero_bits = csiz->lower_bound - size_in_bits;
|
||||
while(trailing_zero_bits > 0) {
|
||||
if(trailing_zero_bits > 8 * sizeof(zeros)) {
|
||||
ret = per_put_many_bits(po, zeros, 8 * sizeof(zeros));
|
||||
trailing_zero_bits -= 8 * sizeof(zeros);
|
||||
} else {
|
||||
ret = per_put_many_bits(po, zeros, trailing_zero_bits);
|
||||
trailing_zero_bits = 0;
|
||||
}
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes", st->size);
|
||||
|
||||
buf = st->buf;
|
||||
do {
|
||||
int need_eom = 0;
|
||||
ssize_t maySave = uper_put_length(po, size_in_bits, &need_eom);
|
||||
if(maySave < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN_DEBUG("Encoding %" ASN_PRI_SSIZE " of %" ASN_PRI_SIZE "", maySave, size_in_bits);
|
||||
|
||||
ret = per_put_many_bits(po, buf, maySave);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
|
||||
buf += maySave >> 3;
|
||||
size_in_bits -= maySave;
|
||||
assert(!(maySave & 0x07) || !size_in_bits);
|
||||
if(need_eom && uper_put_length(po, 0, 0))
|
||||
ASN__ENCODE_FAILED; /* End of Message length */
|
||||
} while(size_in_bits);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BIT_STRING.h"
|
||||
|
||||
static const char *_bit_pattern[16] = {
|
||||
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
|
||||
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
|
||||
};
|
||||
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
char scratch[128];
|
||||
char *p = scratch;
|
||||
char *scend = scratch + (sizeof(scratch) - 10);
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
int xcan = (flags & XER_F_CANONICAL);
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
buf = st->buf;
|
||||
end = buf + st->size - 1; /* Last byte is special */
|
||||
|
||||
/*
|
||||
* Binary dump
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
int v = *buf;
|
||||
int nline = xcan?0:(((buf - st->buf) % 8) == 0);
|
||||
if(p >= scend || nline) {
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
if(nline) ASN__TEXT_INDENT(1, ilevel);
|
||||
}
|
||||
memcpy(p + 0, _bit_pattern[v >> 4], 4);
|
||||
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
|
||||
p += 8;
|
||||
}
|
||||
|
||||
//if(!xcan && ((buf - st->buf) % 8) == 0)
|
||||
// ASN__TEXT_INDENT(1, ilevel);
|
||||
//ASN__CALLBACK(scratch, p - scratch);
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
if(!xcan && ((buf - st->buf) % 8) == 0)
|
||||
ASN__TEXT_INDENT(1, ilevel);
|
||||
p = scratch;
|
||||
|
||||
if(buf == end) {
|
||||
int v = *buf;
|
||||
int ubits = st->bits_unused;
|
||||
int i;
|
||||
for(i = 7; i >= ubits; i--)
|
||||
*p++ = (v & (1 << i)) ? 0x31 : 0x30;
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
}
|
||||
|
||||
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BMPString.h"
|
||||
|
||||
/*
|
||||
* BMPString basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (30 << 2)), /* [UNIVERSAL 30] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
asn_OCTET_STRING_specifics_t asn_SPC_BMPString_specs = {
|
||||
sizeof(BMPString_t),
|
||||
offsetof(BMPString_t, _asn_ctx),
|
||||
ASN_OSUBV_U16 /* 16-bits character */
|
||||
};
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
static asn_per_constraints_t asn_DEF_BMPString_per_constraints = {
|
||||
{ APC_CONSTRAINED, 16, 16, 0, 65535 },
|
||||
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0
|
||||
};
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
asn_TYPE_operation_t asn_OP_BMPString = {
|
||||
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
BMPString_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber,
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
BMPString_decode_xer, /* Convert from UTF-8 */
|
||||
BMPString_encode_xer, /* Convert to UTF-8 */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
BMPString_decode_jer, /* Convert to UTF-8 */
|
||||
BMPString_encode_jer, /* Convert to UTF-8 */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper,
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper,
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
OCTET_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BMPString = {
|
||||
"BMPString",
|
||||
"BMPString",
|
||||
&asn_OP_BMPString,
|
||||
asn_DEF_BMPString_tags,
|
||||
sizeof(asn_DEF_BMPString_tags)
|
||||
/ sizeof(asn_DEF_BMPString_tags[0]) - 1,
|
||||
asn_DEF_BMPString_tags,
|
||||
sizeof(asn_DEF_BMPString_tags)
|
||||
/ sizeof(asn_DEF_BMPString_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
&asn_DEF_BMPString_per_constraints,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
BMPString_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_BMPString_specs
|
||||
};
|
||||
|
||||
int
|
||||
BMPString_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const BMPString_t *st = (const BMPString_t *)sptr;
|
||||
|
||||
if(st && st->buf) {
|
||||
if(st->size & 1) {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: invalid size %" ASN_PRI_SIZE " not divisible by 2 (%s:%d)",
|
||||
td->name, st->size, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ASN__CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name,
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT) || !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
/*
|
||||
* BMPString specific contents printer.
|
||||
*/
|
||||
ssize_t
|
||||
BMPString__dump(const BMPString_t *st,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
char scratch[128]; /* Scratchpad buffer */
|
||||
char *p = scratch;
|
||||
ssize_t wrote = 0;
|
||||
uint8_t *ch;
|
||||
uint8_t *end;
|
||||
|
||||
ch = st->buf;
|
||||
end = (st->buf + st->size);
|
||||
for(end--; ch < end; ch += 2) {
|
||||
uint16_t wc = (ch[0] << 8) | ch[1]; /* 2 bytes */
|
||||
if(sizeof(scratch) - (p - scratch) < 3) {
|
||||
wrote += p - scratch;
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
p = scratch;
|
||||
}
|
||||
if(wc < 0x80) {
|
||||
*p++ = (char)wc;
|
||||
} else if(wc < 0x800) {
|
||||
*p++ = 0xc0 | ((wc >> 6));
|
||||
*p++ = 0x80 | ((wc & 0x3f));
|
||||
} else {
|
||||
*p++ = 0xe0 | ((wc >> 12));
|
||||
*p++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*p++ = 0x80 | ((wc & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
wrote += p - scratch;
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
|
||||
return wrote;
|
||||
}
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) || !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
@@ -0,0 +1,67 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BMPString_H_
|
||||
#define _BMPString_H_
|
||||
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t BMPString_t; /* Implemented via OCTET STRING */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BMPString;
|
||||
extern asn_TYPE_operation_t asn_OP_BMPString;
|
||||
extern asn_OCTET_STRING_specifics_t asn_SPC_BMPString_specs;
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT) || !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
ssize_t BMPString__dump(const BMPString_t *st, asn_app_consume_bytes_f *cb, void *app_key);
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) || !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#define BMPString_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f BMPString_print; /* Human-readable output */
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define BMPString_compare OCTET_STRING_compare
|
||||
#define BMPString_copy OCTET_STRING_copy
|
||||
|
||||
asn_constr_check_f BMPString_constraint;
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define BMPString_decode_ber OCTET_STRING_decode_ber
|
||||
#define BMPString_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f BMPString_decode_xer;
|
||||
xer_type_encoder_f BMPString_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f BMPString_decode_jer;
|
||||
jer_type_encoder_f BMPString_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
#define BMPString_decode_uper OCTET_STRING_decode_uper
|
||||
#define BMPString_encode_uper OCTET_STRING_encode_uper
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define BMPString_decode_aper OCTET_STRING_decode_aper
|
||||
#define BMPString_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
#define BMPString_random_fill OCTET_STRING_random_fill
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BMPString_H_ */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BMPString.h"
|
||||
#include "UTF8String.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
BMPString_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints, void **sptr,
|
||||
const void *buf_ptr, size_t size) {
|
||||
asn_dec_rval_t rc;
|
||||
|
||||
rc = OCTET_STRING_decode_jer_utf8(opt_codec_ctx, td, constraints, sptr, buf_ptr, size);
|
||||
if(rc.code == RC_OK) {
|
||||
/*
|
||||
* Now we have a whole string in UTF-8 format.
|
||||
* Convert it into UCS-2.
|
||||
*/
|
||||
uint32_t *wcs;
|
||||
size_t wcs_len;
|
||||
UTF8String_t *st;
|
||||
|
||||
assert(*sptr);
|
||||
st = (UTF8String_t *)*sptr;
|
||||
assert(st->buf);
|
||||
wcs_len = UTF8String_to_wcs(st, 0, 0);
|
||||
|
||||
wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
|
||||
if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
} else {
|
||||
wcs[wcs_len] = 0; /* nul-terminate */
|
||||
}
|
||||
|
||||
if(1) {
|
||||
/* Swap byte order and trim encoding to 2 bytes */
|
||||
uint32_t *wc = wcs;
|
||||
uint32_t *wc_end = wcs + wcs_len;
|
||||
uint16_t *dstwc = (uint16_t *)wcs;
|
||||
for(; wc < wc_end; wc++, dstwc++) {
|
||||
uint32_t wch = *wc;
|
||||
if(wch > 0xffff) {
|
||||
FREEMEM(wcs);
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
}
|
||||
*((uint8_t *)dstwc + 0) = wch >> 8;
|
||||
*((uint8_t *)dstwc + 1) = wch;
|
||||
}
|
||||
dstwc = (uint16_t *)REALLOC(wcs, 2 * (wcs_len + 1));
|
||||
if(!dstwc) {
|
||||
FREEMEM(wcs);
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
} else {
|
||||
dstwc[wcs_len] = 0; /* nul-terminate */
|
||||
wcs = (uint32_t *)(void *)dstwc; /* Alignment OK */
|
||||
}
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = (uint8_t *)wcs;
|
||||
st->size = 2 * wcs_len;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BMPString_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t* constraints,
|
||||
const void *sptr, int ilevel,
|
||||
enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BMPString_t *st = (const BMPString_t *)sptr;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
ssize_t ro_encoded = 0;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__CALLBACK("\"", 1);
|
||||
ro_encoded = BMPString__dump(st, cb, app_key);
|
||||
if(ro_encoded < 0) goto cb_failed;
|
||||
er.encoded += ro_encoded;
|
||||
ASN__CALLBACK("\"", 1);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BMPString.h"
|
||||
|
||||
int
|
||||
BMPString_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BMPString_t *st = (const BMPString_t *)sptr;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(!st || !st->buf)
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
|
||||
if(BMPString__dump(st, cb, app_key) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BMPString.h"
|
||||
#include "UTF8String.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
BMPString_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
asn_dec_rval_t rc;
|
||||
|
||||
rc = OCTET_STRING_decode_xer_utf8(opt_codec_ctx, td, sptr, opt_mname,
|
||||
buf_ptr, size);
|
||||
if(rc.code == RC_OK) {
|
||||
/*
|
||||
* Now we have a whole string in UTF-8 format.
|
||||
* Convert it into UCS-2.
|
||||
*/
|
||||
uint32_t *wcs;
|
||||
size_t wcs_len;
|
||||
UTF8String_t *st;
|
||||
|
||||
assert(*sptr);
|
||||
st = (UTF8String_t *)*sptr;
|
||||
assert(st->buf);
|
||||
wcs_len = UTF8String_to_wcs(st, 0, 0);
|
||||
|
||||
wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
|
||||
if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
} else {
|
||||
wcs[wcs_len] = 0; /* nul-terminate */
|
||||
}
|
||||
|
||||
if(1) {
|
||||
/* Swap byte order and trim encoding to 2 bytes */
|
||||
uint32_t *wc = wcs;
|
||||
uint32_t *wc_end = wcs + wcs_len;
|
||||
uint16_t *dstwc = (uint16_t *)wcs;
|
||||
for(; wc < wc_end; wc++, dstwc++) {
|
||||
uint32_t wch = *wc;
|
||||
if(wch > 0xffff) {
|
||||
FREEMEM(wcs);
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
}
|
||||
*((uint8_t *)dstwc + 0) = wch >> 8;
|
||||
*((uint8_t *)dstwc + 1) = wch;
|
||||
}
|
||||
dstwc = (uint16_t *)REALLOC(wcs, 2 * (wcs_len + 1));
|
||||
if(!dstwc) {
|
||||
FREEMEM(wcs);
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
} else {
|
||||
dstwc[wcs_len] = 0; /* nul-terminate */
|
||||
wcs = (uint32_t *)(void *)dstwc; /* Alignment OK */
|
||||
}
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = (uint8_t *)wcs;
|
||||
st->size = 2 * wcs_len;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BMPString_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BMPString_t *st = (const BMPString_t *)sptr;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = BMPString__dump(st, cb, app_key);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
/*
|
||||
* BOOLEAN basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_BOOLEAN = {
|
||||
BOOLEAN_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
BOOLEAN_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
BOOLEAN_compare,
|
||||
BOOLEAN_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
BOOLEAN_decode_ber,
|
||||
BOOLEAN_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
BOOLEAN_decode_xer,
|
||||
BOOLEAN_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
BOOLEAN_decode_jer,
|
||||
BOOLEAN_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
BOOLEAN_decode_oer,
|
||||
BOOLEAN_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
BOOLEAN_decode_uper, /* Unaligned PER decoder */
|
||||
BOOLEAN_encode_uper, /* Unaligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
BOOLEAN_decode_aper, /* Aligned PER decoder */
|
||||
BOOLEAN_encode_aper, /* Aligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
BOOLEAN_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
|
||||
"BOOLEAN",
|
||||
"BOOLEAN",
|
||||
&asn_OP_BOOLEAN,
|
||||
asn_DEF_BOOLEAN_tags,
|
||||
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
|
||||
asn_DEF_BOOLEAN_tags, /* Same as above */
|
||||
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
void
|
||||
BOOLEAN_free(const asn_TYPE_descriptor_t *td, void *ptr,
|
||||
enum asn_struct_free_method method) {
|
||||
if(td && ptr) {
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(ptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET:
|
||||
memset(ptr, 0, sizeof(BOOLEAN_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
BOOLEAN_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
|
||||
const void *bptr) {
|
||||
const BOOLEAN_t *a = aptr;
|
||||
const BOOLEAN_t *b = bptr;
|
||||
|
||||
(void)td;
|
||||
|
||||
if(a && b) {
|
||||
if(!*a == !*b) { /* TRUE can be encoded by any non-zero byte. */
|
||||
return 0;
|
||||
} else if(!*a) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if(!a) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
BOOLEAN_copy(const asn_TYPE_descriptor_t *td, void **aptr,
|
||||
const void *bptr) {
|
||||
BOOLEAN_t *a = *aptr;
|
||||
const BOOLEAN_t *b = bptr;
|
||||
|
||||
(void)td;
|
||||
|
||||
if(!b) {
|
||||
if(a) {
|
||||
FREEMEM(a);
|
||||
*aptr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!a) {
|
||||
a = *aptr = MALLOC(sizeof(BOOLEAN_t));
|
||||
if(!a) return -1;
|
||||
}
|
||||
|
||||
*a = *b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BOOLEAN_H_
|
||||
#define _BOOLEAN_H_
|
||||
|
||||
#include "asn_application.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The underlying integer may contain various values, but everything
|
||||
* non-zero is capped to 0xff by the DER encoder. The BER decoder may
|
||||
* yield non-zero values different from 1, beware.
|
||||
*/
|
||||
typedef unsigned BOOLEAN_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN;
|
||||
extern asn_TYPE_operation_t asn_OP_BOOLEAN;
|
||||
|
||||
asn_struct_free_f BOOLEAN_free;
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f BOOLEAN_print;
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f BOOLEAN_compare;
|
||||
asn_struct_copy_f BOOLEAN_copy;
|
||||
|
||||
#define BOOLEAN_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_type_decoder_f BOOLEAN_decode_ber;
|
||||
der_type_encoder_f BOOLEAN_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f BOOLEAN_decode_xer;
|
||||
xer_type_encoder_f BOOLEAN_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f BOOLEAN_decode_jer;
|
||||
jer_type_encoder_f BOOLEAN_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f BOOLEAN_decode_oer;
|
||||
oer_type_encoder_f BOOLEAN_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f BOOLEAN_decode_uper;
|
||||
per_type_encoder_f BOOLEAN_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f BOOLEAN_decode_aper;
|
||||
per_type_encoder_f BOOLEAN_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f BOOLEAN_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BOOLEAN_H_ */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rv;
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
(void)td;
|
||||
|
||||
if(!st) {
|
||||
st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a single bit
|
||||
*/
|
||||
switch(per_get_few_bits(pd, 1)) {
|
||||
case 1:
|
||||
*st = 1;
|
||||
break;
|
||||
case 0:
|
||||
*st = 0;
|
||||
break;
|
||||
case -1:
|
||||
default:
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
|
||||
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
asn_enc_rval_t er = { 0, 0, 0 };
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
if(per_put_few_bits(po, *st ? 1 : 0, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
/*
|
||||
* Decode BOOLEAN type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **bool_value,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
ber_tlv_len_t lidx;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)",
|
||||
td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
|
||||
tag_mode, 0, &length, 0);
|
||||
if(rval.code != RC_OK)
|
||||
return rval;
|
||||
|
||||
ASN_DEBUG("Boolean length is %d bytes", (int)length);
|
||||
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute boolean value.
|
||||
*/
|
||||
for(*st = 0, lidx = 0;
|
||||
(lidx < length) && *st == 0; lidx++) {
|
||||
/*
|
||||
* Very simple approach: read bytes until the end or
|
||||
* value is already TRUE.
|
||||
* BOOLEAN is not supposed to contain meaningful data anyway.
|
||||
*/
|
||||
*st |= ((const uint8_t *)buf_ptr)[lidx];
|
||||
}
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d",
|
||||
(long)rval.consumed, (long)length,
|
||||
td->name, *st);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
|
||||
erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
|
||||
if(erval.encoded == -1) {
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = sptr;
|
||||
return erval;
|
||||
}
|
||||
|
||||
if(cb) {
|
||||
uint8_t bool_value;
|
||||
|
||||
bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
|
||||
|
||||
if(cb(&bool_value, 1, app_key) < 0) {
|
||||
erval.encoded = -1;
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = sptr;
|
||||
return erval;
|
||||
}
|
||||
}
|
||||
|
||||
erval.encoded += 1;
|
||||
|
||||
ASN__ENCODED_OK(erval);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "asn_codecs_prim.h"
|
||||
#include "BOOLEAN.h"
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Decode the chunk of JSON text encoding INTEGER.
|
||||
*/
|
||||
static enum jer_pbd_rval
|
||||
BOOLEAN__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
|
||||
const char *p = (const char *)chunk_buf;
|
||||
|
||||
(void)td;
|
||||
(void)chunk_size;
|
||||
|
||||
if(p[0] == 't' /* 'true' */) {
|
||||
*st = 1;
|
||||
return JPBD_BODY_CONSUMED;
|
||||
} else if (p[0] == 'f' /* 'false' */) {
|
||||
*st = 0;
|
||||
return JPBD_BODY_CONSUMED;
|
||||
} else {
|
||||
return JPBD_BROKEN_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t* constraints,
|
||||
void **sptr, const void *buf_ptr, size_t size) {
|
||||
return jer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(BOOLEAN_t), buf_ptr, size,
|
||||
BOOLEAN__jer_body_decode);
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel, enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
if(*st) {
|
||||
ASN__CALLBACK("true", 4);
|
||||
} else {
|
||||
ASN__CALLBACK("false", 5);
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, const void *sptr,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er = { 1, 0, 0 };
|
||||
const BOOLEAN_t *st = sptr;
|
||||
uint8_t bool_value = *st ? 0xff : 0; /* 0xff mandated by OER */
|
||||
|
||||
(void)td;
|
||||
(void)constraints; /* Constraints are unused in OER */
|
||||
|
||||
if(cb(&bool_value, 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
asn_dec_rval_t ok = {RC_OK, 1};
|
||||
BOOLEAN_t *st;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints; /* Constraints are unused in OER */
|
||||
|
||||
if(size < 1) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
if(!(st = *sptr)) {
|
||||
st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*st = *(const uint8_t *)ptr;
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
int
|
||||
BOOLEAN_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
const char *buf;
|
||||
size_t buflen;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(st) {
|
||||
if(*st) {
|
||||
buf = "TRUE";
|
||||
buflen = 4;
|
||||
} else {
|
||||
buf = "FALSE";
|
||||
buflen = 5;
|
||||
}
|
||||
} else {
|
||||
buf = "<absent>";
|
||||
buflen = 8;
|
||||
}
|
||||
|
||||
return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
asn_random_fill_result_t
|
||||
BOOLEAN_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
BOOLEAN_t *st = *sptr;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
if(!constraints || !constraints->per_constraints)
|
||||
constraints = &td->encoding_constraints;
|
||||
if(constraints->per_constraints) {
|
||||
const asn_per_constraint_t *pc = &constraints->per_constraints->value;
|
||||
if(pc->flags & APC_CONSTRAINED) {
|
||||
*st = asn_random_between(pc->lower_bound, pc->upper_bound);
|
||||
return result_ok;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(!constraints) constraints = &td->encoding_constraints;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
/* Simulate booleans that are sloppily set and biased. */
|
||||
switch(asn_random_between(0, 7)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
*st = 0; break;
|
||||
case 3: *st = -1; break;
|
||||
case 4: *st = 1; break;
|
||||
case 5: *st = INT_MIN; break;
|
||||
case 6: *st = INT_MAX; break;
|
||||
default:
|
||||
*st = asn_random_between(INT_MIN, INT_MAX);
|
||||
break;
|
||||
}
|
||||
return result_ok;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "BOOLEAN.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rv;
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
|
||||
if(!st) {
|
||||
st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a single bit
|
||||
*/
|
||||
switch(per_get_few_bits(pd, 1)) {
|
||||
case 1: *st = 1; break;
|
||||
case 0: *st = 0; break;
|
||||
case -1: default: ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
|
||||
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, const void *sptr,
|
||||
asn_per_outp_t *po) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
asn_enc_rval_t er = { 0, 0, 0 };
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
if(per_put_few_bits(po, *st ? 1 : 0, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "asn_codecs_prim.h"
|
||||
#include "BOOLEAN.h"
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding INTEGER.
|
||||
*/
|
||||
static enum xer_pbd_rval
|
||||
BOOLEAN__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
|
||||
const char *p = (const char *)chunk_buf;
|
||||
|
||||
(void)td;
|
||||
|
||||
if(chunk_size && p[0] == 0x3c /* '<' */) {
|
||||
switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
|
||||
case XCT_BOTH:
|
||||
/* "<false/>" */
|
||||
*st = 0;
|
||||
break;
|
||||
case XCT_UNKNOWN_BO:
|
||||
if(xer_check_tag(chunk_buf, chunk_size, "true") != XCT_BOTH)
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
/* "<true/>" */
|
||||
*st = 1; /* Or 0xff as in DER?.. */
|
||||
break;
|
||||
default:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
}
|
||||
return XPBD_BODY_CONSUMED;
|
||||
} else {
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
return xer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
|
||||
BOOLEAN__xer_body_decode);
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
if(*st) {
|
||||
ASN__CALLBACK("<true/>", 7);
|
||||
} else {
|
||||
ASN__CALLBACK("<false/>", 8);
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005, 2006 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ENUMERATED.h"
|
||||
|
||||
/*
|
||||
* ENUMERATED basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_ENUMERATED_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_ENUMERATED = {
|
||||
ASN__PRIMITIVE_TYPE_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
INTEGER_print, /* Implemented in terms of INTEGER */
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
INTEGER_compare, /* Implemented in terms of INTEGER */
|
||||
INTEGER_copy, /* Implemented in terms of INTEGER */
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_decode_primitive,
|
||||
INTEGER_encode_der, /* Implemented in terms of INTEGER */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
INTEGER_decode_xer, /* This is temporary! */
|
||||
INTEGER_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
ENUMERATED_decode_jer,
|
||||
INTEGER_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
ENUMERATED_decode_oer,
|
||||
ENUMERATED_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
ENUMERATED_decode_uper, /* Unaligned PER decoder */
|
||||
ENUMERATED_encode_uper, /* Unaligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
ENUMERATED_decode_aper, /* Aligned PER decoder */
|
||||
ENUMERATED_encode_aper, /* Aligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
ENUMERATED_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
|
||||
"ENUMERATED",
|
||||
"ENUMERATED",
|
||||
&asn_OP_ENUMERATED,
|
||||
asn_DEF_ENUMERATED_tags,
|
||||
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
|
||||
asn_DEF_ENUMERATED_tags, /* Same as above */
|
||||
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _ENUMERATED_H_
|
||||
#define _ENUMERATED_H_
|
||||
|
||||
#include "INTEGER.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef INTEGER_t ENUMERATED_t; /* Implemented via INTEGER */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ENUMERATED;
|
||||
extern asn_TYPE_operation_t asn_OP_ENUMERATED;
|
||||
|
||||
#define ENUMERATED_free ASN__PRIMITIVE_TYPE_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define ENUMERATED_print INTEGER_print
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define ENUMERATED_compare INTEGER_compare
|
||||
#define ENUMERATED_copy INTEGER_copy
|
||||
|
||||
#define ENUMERATED_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define ENUMERATED_decode_ber ber_decode_primitive
|
||||
#define ENUMERATED_encode_der INTEGER_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define ENUMERATED_decode_xer INTEGER_decode_xer
|
||||
#define ENUMERATED_encode_xer INTEGER_encode_xer
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f ENUMERATED_decode_jer;
|
||||
#define ENUMERATED_encode_jer INTEGER_encode_jer
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f ENUMERATED_decode_oer;
|
||||
oer_type_encoder_f ENUMERATED_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f ENUMERATED_decode_uper;
|
||||
per_type_encoder_f ENUMERATED_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f ENUMERATED_decode_aper;
|
||||
per_type_encoder_f ENUMERATED_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
#define ENUMERATED_random_fill INTEGER_random_fill
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ENUMERATED_H_ */
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ENUMERATED.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
ENUMERATED_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rval;
|
||||
ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
|
||||
long value;
|
||||
void *vptr = &value;
|
||||
|
||||
if(!st) {
|
||||
st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
rval = NativeEnumerated_decode_aper(opt_codec_ctx, td, constraints,
|
||||
(void **)&vptr, pd);
|
||||
if(rval.code == RC_OK)
|
||||
if(asn_long2INTEGER(st, value))
|
||||
rval.code = RC_FAIL;
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
ENUMERATED_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const ENUMERATED_t *st = (const ENUMERATED_t *)sptr;
|
||||
long value;
|
||||
|
||||
if(asn_INTEGER2long(st, &value))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
return NativeEnumerated_encode_aper(td, constraints, &value, po);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ENUMERATED.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
struct e2v_key {
|
||||
const char *start;
|
||||
const char *stop;
|
||||
const asn_INTEGER_enum_map_t *vemap;
|
||||
const unsigned int *evmap;
|
||||
};
|
||||
static int
|
||||
ENUMERATED__jer_compar_enum2value(const void *kp, const void *am) {
|
||||
const struct e2v_key *key = (const struct e2v_key *)kp;
|
||||
const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
|
||||
const char *ptr, *end, *name;
|
||||
|
||||
/* Remap the element (sort by different criterion) */
|
||||
el = key->vemap + key->evmap[el - key->vemap];
|
||||
|
||||
/* Compare strings */
|
||||
for(ptr = key->start, end = key->stop, name = el->enum_name;
|
||||
ptr < end; ptr++, name++) {
|
||||
if(*ptr != *name || !*name)
|
||||
return *(const unsigned char *)ptr - *(const unsigned char *)name;
|
||||
}
|
||||
return name[0] ? -1 : 0;
|
||||
}
|
||||
|
||||
static const asn_INTEGER_enum_map_t *
|
||||
ENUMERATED_jer_map_enum2value(const asn_INTEGER_specifics_t *specs, const char *lstart,
|
||||
const char *lstop) {
|
||||
const asn_INTEGER_enum_map_t *el_found;
|
||||
int count = specs ? specs->map_count : 0;
|
||||
struct e2v_key key;
|
||||
const char *lp;
|
||||
|
||||
if(!count) return NULL;
|
||||
|
||||
/* Guaranteed: assert(lstart < lstop); */
|
||||
/* Figure out the tag name */
|
||||
for(lstart++, lp = lstart; lp < lstop; lp++) {
|
||||
switch(*lp) {
|
||||
case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
|
||||
case 0x22: /* '"' */
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(lp == lstop) return NULL; /* No tag found */
|
||||
lstop = lp;
|
||||
|
||||
key.start = lstart;
|
||||
key.stop = lstop;
|
||||
key.vemap = specs->value2enum;
|
||||
key.evmap = specs->enum2value;
|
||||
el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
|
||||
specs->value2enum, count, sizeof(specs->value2enum[0]),
|
||||
ENUMERATED__jer_compar_enum2value);
|
||||
if(el_found) {
|
||||
/* Remap enum2value into value2enum */
|
||||
el_found = key.vemap + key.evmap[el_found - key.vemap];
|
||||
}
|
||||
return el_found;
|
||||
}
|
||||
|
||||
static enum jer_pbd_rval
|
||||
ENUMERATED__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
INTEGER_t *st = (INTEGER_t *)sptr;
|
||||
intmax_t dec_value;
|
||||
const char *lp;
|
||||
const char *lstart = (const char *)chunk_buf;
|
||||
const char *lstop = lstart + chunk_size;
|
||||
int decoded = 0;
|
||||
|
||||
for (lp = lstart; lp < lstop; ++lp) {
|
||||
if (*lp == 0x22 /* '"' */) {
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
el = ENUMERATED_jer_map_enum2value(
|
||||
(const asn_INTEGER_specifics_t *)
|
||||
td->specifics, lstart, lstop);
|
||||
if(el) {
|
||||
ASN_DEBUG("Found \"%s\" => %ld",
|
||||
el->enum_name, el->nat_value);
|
||||
dec_value = el->nat_value;
|
||||
decoded = 1;
|
||||
lp = lstop - 1;
|
||||
continue;
|
||||
}
|
||||
ASN_DEBUG("Unknown identifier for ENUMERATED");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!decoded) {
|
||||
return JPBD_BROKEN_ENCODING;;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the result of parsing of enumeration into a BER representation.
|
||||
*/
|
||||
if(asn_imax2INTEGER(st, dec_value)) {
|
||||
ASN_DEBUG("ENUMERATED decode %s conversion failed", td->name);
|
||||
return JPBD_SYSTEM_FAILURE;
|
||||
}
|
||||
|
||||
return JPBD_BODY_CONSUMED;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
ENUMERATED_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
void **sptr, const void *buf_ptr, size_t size) {
|
||||
return jer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(INTEGER_t),
|
||||
buf_ptr, size, ENUMERATED__jer_body_decode);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ENUMERATED.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
ENUMERATED_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
asn_dec_rval_t rval;
|
||||
ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
|
||||
long value;
|
||||
void *vptr = &value;
|
||||
|
||||
if(!st) {
|
||||
st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
rval = NativeEnumerated_decode_oer(opt_codec_ctx, td, constraints,
|
||||
(void **)&vptr, ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
if(asn_long2INTEGER(st, value)) {
|
||||
rval.code = RC_FAIL;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
ENUMERATED_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const ENUMERATED_t *st = sptr;
|
||||
long value;
|
||||
|
||||
if(asn_INTEGER2long(st, &value)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
return NativeEnumerated_encode_oer(td, constraints, &value, cb, app_key);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ENUMERATED.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
ENUMERATED_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rval;
|
||||
ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
|
||||
long value;
|
||||
void *vptr = &value;
|
||||
|
||||
if(!st) {
|
||||
st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
rval = NativeEnumerated_decode_uper(opt_codec_ctx, td, constraints,
|
||||
(void **)&vptr, pd);
|
||||
if(rval.code == RC_OK) {
|
||||
if(asn_long2INTEGER(st, value)) {
|
||||
rval.code = RC_FAIL;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
ENUMERATED_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const ENUMERATED_t *st = (const ENUMERATED_t *)sptr;
|
||||
long value;
|
||||
|
||||
if(asn_INTEGER2long(st, &value)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
return NativeEnumerated_encode_uper(td, constraints, &value, po);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralString.h"
|
||||
|
||||
/*
|
||||
* GeneralString basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_GeneralString_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (27 << 2)), /* [UNIVERSAL 27] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_GeneralString = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
OCTET_STRING_print, /* non-ascii string */
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_hex,
|
||||
OCTET_STRING_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_hex,
|
||||
OCTET_STRING_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
OCTET_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_GeneralString = {
|
||||
"GeneralString",
|
||||
"GeneralString",
|
||||
&asn_OP_GeneralString,
|
||||
asn_DEF_GeneralString_tags,
|
||||
sizeof(asn_DEF_GeneralString_tags)
|
||||
/ sizeof(asn_DEF_GeneralString_tags[0]) - 1,
|
||||
asn_DEF_GeneralString_tags,
|
||||
sizeof(asn_DEF_GeneralString_tags)
|
||||
/ sizeof(asn_DEF_GeneralString_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_unknown_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _GeneralString_H_
|
||||
#define _GeneralString_H_
|
||||
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t GeneralString_t; /* Implemented via OCTET STRING */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_GeneralString;
|
||||
extern asn_TYPE_operation_t asn_OP_GeneralString;
|
||||
|
||||
#define GeneralString_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define GeneralString_print OCTET_STRING_print
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define GeneralString_compare OCTET_STRING_compare
|
||||
#define GeneralString_copy OCTET_STRING_copy
|
||||
|
||||
#define GeneralString_constraint asn_generic_unknown_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define GeneralString_decode_ber OCTET_STRING_decode_ber
|
||||
#define GeneralString_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define GeneralString_decode_xer OCTET_STRING_decode_xer_hex
|
||||
#define GeneralString_encode_xer OCTET_STRING_encode_xer
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
#define GeneralString_decode_jer OCTET_STRING_decode_jer_hex
|
||||
#define GeneralString_encode_jer OCTET_STRING_encode_jer
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
#define GeneralString_decode_uper OCTET_STRING_decode_uper
|
||||
#define GeneralString_encode_uper OCTET_STRING_encode_uper
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define GeneralString_decode_aper OCTET_STRING_decode_aper
|
||||
#define GeneralString_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GeneralString_H_ */
|
||||
@@ -0,0 +1,751 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2019 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#define _POSIX_PTHREAD_SEMANTICS /* for Sun */
|
||||
#ifndef _REENTRANT
|
||||
#define _REENTRANT /* for Sun */
|
||||
#endif
|
||||
#define __EXTENSIONS__ /* for Sun */
|
||||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE /* for timegm(3) */
|
||||
#endif
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralizedTime.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "/usr/include/time.h"
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma message( "PLEASE STOP AND READ!")
|
||||
#pragma message( " localtime_r is implemented via localtime(), which may be not thread-safe.")
|
||||
#pragma message( " gmtime_r is implemented via gmtime(), which may be not thread-safe.")
|
||||
#pragma message( " ")
|
||||
#pragma message( " You must fix the code by inserting appropriate locking")
|
||||
#pragma message( " if you want to use asn_GT2time() or asn_UT2time().")
|
||||
#pragma message( "PLEASE STOP AND READ!")
|
||||
|
||||
static struct tm *localtime_r(const time_t *tloc, struct tm *result) {
|
||||
struct tm *tm;
|
||||
if((tm = localtime(tloc)))
|
||||
return memcpy(result, tm, sizeof(struct tm));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tm *gmtime_r(const time_t *tloc, struct tm *result) {
|
||||
struct tm *tm;
|
||||
if((tm = gmtime(tloc)))
|
||||
return memcpy(result, tm, sizeof(struct tm));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define tzset() _tzset()
|
||||
#define putenv(c) _putenv(c)
|
||||
#define _EMULATE_TIMEGM
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if defined(sun) || defined(__sun) || defined(__solaris__)
|
||||
#define _EMULATE_TIMEGM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Where to look for offset from GMT, Phase I.
|
||||
* Several platforms are known.
|
||||
*/
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) \
|
||||
|| (defined(__GNUC__) && defined(__APPLE_CC__)) \
|
||||
|| (defined __GLIBC__ && __GLIBC__ >= 2)
|
||||
#undef HAVE_TM_GMTOFF
|
||||
#define HAVE_TM_GMTOFF
|
||||
#endif /* BSDs and newer glibc */
|
||||
|
||||
/*
|
||||
* Where to look for offset from GMT, Phase II.
|
||||
*/
|
||||
#ifdef HAVE_TM_GMTOFF
|
||||
#define GMTOFF(tm) ((tm).tm_gmtoff)
|
||||
#else /* HAVE_TM_GMTOFF */
|
||||
#define GMTOFF(tm) (_timezone)
|
||||
#endif /* HAVE_TM_GMTOFF */
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma message( "PLEASE STOP AND READ!")
|
||||
#pragma message( " timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe.")
|
||||
#pragma message( " ")
|
||||
#pragma message( " You must fix the code by inserting appropriate locking")
|
||||
#pragma message( " if you want to use asn_GT2time() or asn_UT2time().")
|
||||
#pragma message( "PLEASE STOP AND READ!")
|
||||
#else
|
||||
#if defined(_EMULATE_TIMEGM) || (!defined(HAVE_TM_GMTOFF) && !defined(HAVE_TIMEGM))
|
||||
#warning "PLEASE STOP AND READ!"
|
||||
#warning " timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe."
|
||||
#warning " "
|
||||
#warning " You must fix the code by inserting appropriate locking"
|
||||
#warning " if you want to use asn_GT2time() or asn_UT2time()."
|
||||
#warning "PLEASE STOP AND READ!"
|
||||
#endif /* _EMULATE_TIMEGM */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Override our GMTOFF decision for other known platforms.
|
||||
*/
|
||||
#ifdef __CYGWIN__
|
||||
#undef GMTOFF
|
||||
static long GMTOFF(struct tm a){
|
||||
struct tm *lt;
|
||||
time_t local_time, gmt_time;
|
||||
long zone;
|
||||
|
||||
tzset();
|
||||
gmt_time = time (NULL);
|
||||
|
||||
lt = gmtime(&gmt_time);
|
||||
|
||||
local_time = mktime(lt);
|
||||
return (gmt_time - local_time);
|
||||
}
|
||||
#define _EMULATE_TIMEGM
|
||||
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#define ATZVARS do { \
|
||||
char tzoldbuf[64]; \
|
||||
char *tzold
|
||||
#define ATZSAVETZ do { \
|
||||
tzold = getenv("TZ"); \
|
||||
if(tzold) { \
|
||||
size_t tzlen = strlen(tzold); \
|
||||
if(tzlen < sizeof(tzoldbuf)) { \
|
||||
tzold = memcpy(tzoldbuf, tzold, tzlen + 1); \
|
||||
} else { \
|
||||
char *dupptr = tzold; \
|
||||
tzold = MALLOC(tzlen + 1); \
|
||||
if(tzold) memcpy(tzold, dupptr, tzlen + 1); \
|
||||
} \
|
||||
setenv("TZ", "UTC", 1); \
|
||||
} \
|
||||
tzset(); \
|
||||
} while(0)
|
||||
#define ATZOLDTZ do { \
|
||||
if (tzold) { \
|
||||
setenv("TZ", tzold, 1); \
|
||||
*tzoldbuf = 0; \
|
||||
if(tzold != tzoldbuf) \
|
||||
FREEMEM(tzold); \
|
||||
} else { \
|
||||
unsetenv("TZ"); \
|
||||
} \
|
||||
tzset(); \
|
||||
} while(0); } while(0);
|
||||
|
||||
#ifndef HAVE_TIMEGM
|
||||
#ifdef _EMULATE_TIMEGM
|
||||
#include <stdlib.h>
|
||||
static time_t timegm(struct tm *tm) {
|
||||
time_t tloc;
|
||||
ATZVARS;
|
||||
ATZSAVETZ;
|
||||
tloc = mktime(tm);
|
||||
ATZOLDTZ;
|
||||
return tloc;
|
||||
}
|
||||
#endif /* _EMULATE_TIMEGM */
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ASN___INTERNAL_TEST_MODE
|
||||
|
||||
/*
|
||||
* GeneralizedTime basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_GeneralizedTime_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (24 << 2)), /* [UNIVERSAL 24] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
static asn_per_constraints_t asn_DEF_GeneralizedTime_per_constraints = {
|
||||
{ APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
|
||||
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
|
||||
0, 0
|
||||
};
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
asn_TYPE_operation_t asn_OP_GeneralizedTime = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
GeneralizedTime_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
GeneralizedTime_compare,
|
||||
GeneralizedTime_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
GeneralizedTime_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_utf8,
|
||||
GeneralizedTime_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_utf8,
|
||||
GeneralizedTime_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper,
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper,
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
GeneralizedTime_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
|
||||
"GeneralizedTime",
|
||||
"GeneralizedTime",
|
||||
&asn_OP_GeneralizedTime,
|
||||
asn_DEF_GeneralizedTime_tags,
|
||||
sizeof(asn_DEF_GeneralizedTime_tags)
|
||||
/ sizeof(asn_DEF_GeneralizedTime_tags[0]) - 2,
|
||||
asn_DEF_GeneralizedTime_tags,
|
||||
sizeof(asn_DEF_GeneralizedTime_tags)
|
||||
/ sizeof(asn_DEF_GeneralizedTime_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
&asn_DEF_GeneralizedTime_per_constraints,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
GeneralizedTime_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
#endif /* ASN___INTERNAL_TEST_MODE */
|
||||
|
||||
/*
|
||||
* Check that the time looks like the time.
|
||||
*/
|
||||
int
|
||||
GeneralizedTime_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb,
|
||||
void *app_key) {
|
||||
const GeneralizedTime_t *st = (const GeneralizedTime_t *)sptr;
|
||||
time_t tloc;
|
||||
|
||||
errno = EPERM; /* Just an unlikely error code */
|
||||
tloc = asn_GT2time(st, 0, 0);
|
||||
if(tloc == -1 && errno != EPERM) {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: Invalid time format: %s (%s:%d)",
|
||||
td->name, strerror(errno), __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t
|
||||
asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm, int as_gmt) {
|
||||
return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
|
||||
}
|
||||
|
||||
time_t
|
||||
asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits, struct tm *ret_tm, int as_gmt) {
|
||||
time_t tloc;
|
||||
int fv, fd = 0;
|
||||
|
||||
if(frac_value)
|
||||
tloc = asn_GT2time_frac(st, &fv, &fd, ret_tm, as_gmt);
|
||||
else
|
||||
return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
|
||||
if(fd == 0 || frac_digits <= 0) {
|
||||
*frac_value = 0;
|
||||
} else {
|
||||
while(fd > frac_digits)
|
||||
fv /= 10, fd--;
|
||||
while(fd < frac_digits) {
|
||||
if(fv < INT_MAX / 10) {
|
||||
fv *= 10;
|
||||
fd++;
|
||||
} else {
|
||||
/* Too long precision request */
|
||||
fv = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*frac_value = fv;
|
||||
}
|
||||
|
||||
return tloc;
|
||||
}
|
||||
|
||||
time_t
|
||||
asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits, struct tm *ret_tm, int as_gmt) {
|
||||
struct tm tm_s;
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
int gmtoff_h = 0;
|
||||
int gmtoff_m = 0;
|
||||
int gmtoff = 0; /* h + m */
|
||||
int offset_specified = 0;
|
||||
int fvalue = 0;
|
||||
int fdigits = 0;
|
||||
time_t tloc;
|
||||
|
||||
if(!st || !st->buf) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
} else {
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
}
|
||||
|
||||
if(st->size < 10) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode first 10 bytes: "AAAAMMJJhh"
|
||||
*/
|
||||
memset(&tm_s, 0, sizeof(tm_s));
|
||||
#undef B2F
|
||||
#undef B2T
|
||||
#define B2F(var) do { \
|
||||
unsigned ch = *buf; \
|
||||
if(ch < 0x30 || ch > 0x39) { \
|
||||
errno = EINVAL; \
|
||||
return -1; \
|
||||
} else { \
|
||||
var = var * 10 + (ch - 0x30); \
|
||||
buf++; \
|
||||
} \
|
||||
} while(0)
|
||||
#define B2T(var) B2F(tm_s.var)
|
||||
|
||||
B2T(tm_year); /* 1: A */
|
||||
B2T(tm_year); /* 2: A */
|
||||
B2T(tm_year); /* 3: A */
|
||||
B2T(tm_year); /* 4: A */
|
||||
B2T(tm_mon); /* 5: M */
|
||||
B2T(tm_mon); /* 6: M */
|
||||
B2T(tm_mday); /* 7: J */
|
||||
B2T(tm_mday); /* 8: J */
|
||||
B2T(tm_hour); /* 9: h */
|
||||
B2T(tm_hour); /* 0: h */
|
||||
|
||||
if(buf == end) goto local_finish;
|
||||
|
||||
/*
|
||||
* Parse [mm[ss[(.|,)ffff]]]
|
||||
* ^^
|
||||
*/
|
||||
switch(*buf) {
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
tm_s.tm_min = (*buf++) - 0x30;
|
||||
if(buf == end) { errno = EINVAL; return -1; }
|
||||
B2T(tm_min);
|
||||
break;
|
||||
case 0x2B: case 0x2D: /* +, - */
|
||||
goto offset;
|
||||
case 0x5A: /* Z */
|
||||
goto utc_finish;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(buf == end) goto local_finish;
|
||||
|
||||
/*
|
||||
* Parse [mm[ss[(.|,)ffff]]]
|
||||
* ^^
|
||||
*/
|
||||
switch(*buf) {
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
tm_s.tm_sec = (*buf++) - 0x30;
|
||||
if(buf == end) { errno = EINVAL; return -1; }
|
||||
B2T(tm_sec);
|
||||
break;
|
||||
case 0x2B: case 0x2D: /* +, - */
|
||||
goto offset;
|
||||
case 0x5A: /* Z */
|
||||
goto utc_finish;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(buf == end) goto local_finish;
|
||||
|
||||
/*
|
||||
* Parse [mm[ss[(.|,)ffff]]]
|
||||
* ^ ^
|
||||
*/
|
||||
switch(*buf) {
|
||||
case 0x2C: case 0x2E: /* (.|,) */
|
||||
/*
|
||||
* Process fractions of seconds.
|
||||
*/
|
||||
for(buf++; buf < end; buf++) {
|
||||
int v = *buf;
|
||||
/* GCC 4.x is being too smart without volatile */
|
||||
switch(v) {
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
if(fvalue < INT_MAX/10) {
|
||||
fvalue = fvalue * 10 + (v - 0x30);
|
||||
fdigits++;
|
||||
} else {
|
||||
/* Not enough precision, ignore */
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(buf == end) goto local_finish;
|
||||
|
||||
switch(*buf) {
|
||||
case 0x2B: case 0x2D: /* +, - */
|
||||
goto offset;
|
||||
case 0x5A: /* Z */
|
||||
goto utc_finish;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
offset:
|
||||
|
||||
if(end - buf < 3) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
buf++;
|
||||
B2F(gmtoff_h);
|
||||
B2F(gmtoff_h);
|
||||
if(buf[-3] == 0x2D) /* Negative */
|
||||
gmtoff = -1;
|
||||
else
|
||||
gmtoff = 1;
|
||||
|
||||
if((end - buf) == 2) {
|
||||
B2F(gmtoff_m);
|
||||
B2F(gmtoff_m);
|
||||
} else if(end != buf) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
gmtoff = gmtoff * (3600 * gmtoff_h + 60 * gmtoff_m);
|
||||
|
||||
/* Fall through */
|
||||
utc_finish:
|
||||
|
||||
offset_specified = 1;
|
||||
|
||||
/* Fall through */
|
||||
local_finish:
|
||||
|
||||
/*
|
||||
* Validation.
|
||||
*/
|
||||
if((tm_s.tm_mon > 12 || tm_s.tm_mon < 1)
|
||||
|| (tm_s.tm_mday > 31 || tm_s.tm_mday < 1)
|
||||
|| (tm_s.tm_hour > 23)
|
||||
|| (tm_s.tm_sec > 60)
|
||||
) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Canonicalize */
|
||||
tm_s.tm_mon -= 1; /* 0 - 11 */
|
||||
tm_s.tm_year -= 1900;
|
||||
tm_s.tm_isdst = -1;
|
||||
|
||||
tm_s.tm_sec -= gmtoff;
|
||||
|
||||
/*** AT THIS POINT tm_s is either GMT or local (unknown) ****/
|
||||
|
||||
if(offset_specified) {
|
||||
tloc = timegm(&tm_s);
|
||||
} else {
|
||||
/*
|
||||
* Without an offset (or "Z"),
|
||||
* we can only guess that it is a local zone.
|
||||
* Interpret it in this fashion.
|
||||
*/
|
||||
tloc = mktime(&tm_s);
|
||||
}
|
||||
if(tloc == -1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret_tm) {
|
||||
if(as_gmt) {
|
||||
if(offset_specified) {
|
||||
*ret_tm = tm_s;
|
||||
} else {
|
||||
if(gmtime_r(&tloc, ret_tm) == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(localtime_r(&tloc, ret_tm) == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fractions of seconds */
|
||||
if(frac_value) *frac_value = fvalue;
|
||||
if(frac_digits) *frac_digits = fdigits;
|
||||
|
||||
return tloc;
|
||||
}
|
||||
|
||||
GeneralizedTime_t *
|
||||
asn_time2GT(GeneralizedTime_t *opt_gt, const struct tm *tm, int force_gmt) {
|
||||
return asn_time2GT_frac(opt_gt, tm, 0, 0, force_gmt);
|
||||
}
|
||||
|
||||
GeneralizedTime_t *
|
||||
asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value, int frac_digits, int force_gmt) {
|
||||
struct tm tm_s;
|
||||
long gmtoff = 0;
|
||||
const unsigned int buf_size =
|
||||
4 + 2 + 2 /* yyyymmdd */
|
||||
+ 2 + 2 + 2 /* hhmmss */
|
||||
+ 1 + 9 /* .fffffffff */
|
||||
+ 1 + 4 /* +hhmm */
|
||||
+ 1 /* '\0' */
|
||||
;
|
||||
char *buf = NULL;
|
||||
char *p = NULL;
|
||||
int size = 0;
|
||||
|
||||
/* Check arguments */
|
||||
if(!tm) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pre-allocate a buffer of sufficient yet small length */
|
||||
buf = (char *)MALLOC(buf_size);
|
||||
if(!buf) return 0;
|
||||
|
||||
gmtoff = GMTOFF(*tm);
|
||||
|
||||
if(force_gmt && gmtoff) {
|
||||
tm_s = *tm;
|
||||
tm_s.tm_sec -= gmtoff;
|
||||
timegm(&tm_s); /* Fix the time */
|
||||
tm = &tm_s;
|
||||
#ifdef HAVE_TM_GMTOFF
|
||||
assert(!GMTOFF(tm_s)); /* Will fix itself */
|
||||
#else /* !HAVE_TM_GMTOFF */
|
||||
gmtoff = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
size = snprintf(buf, buf_size, "%04d%02d%02d%02d%02d%02d",
|
||||
tm->tm_year + 1900,
|
||||
tm->tm_mon + 1,
|
||||
tm->tm_mday,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec
|
||||
);
|
||||
if(size != 14) {
|
||||
/* Could be assert(size == 14); */
|
||||
FREEMEM(buf);
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = buf + size;
|
||||
|
||||
/*
|
||||
* Deal with fractions.
|
||||
*/
|
||||
if(frac_value > 0 && frac_digits > 0) {
|
||||
char *end = p + 1 + 9; /* '.' + maximum 9 digits */
|
||||
char *z = p;
|
||||
long fbase;
|
||||
*z++ = '.';
|
||||
|
||||
/* Place bounds on precision */
|
||||
while(frac_digits-- > 9)
|
||||
frac_value /= 10;
|
||||
|
||||
/* emulate fbase = pow(10, frac_digits) */
|
||||
for(fbase = 1; frac_digits--;)
|
||||
fbase *= 10;
|
||||
|
||||
do {
|
||||
int digit = frac_value / fbase;
|
||||
if(digit > 9) { z = 0; break; }
|
||||
*z++ = digit + 0x30;
|
||||
frac_value %= fbase;
|
||||
fbase /= 10;
|
||||
} while(fbase > 0 && frac_value > 0 && z < end);
|
||||
if(z) {
|
||||
for(--z; *z == 0x30; --z); /* Strip zeroes */
|
||||
p = z + (*z != '.');
|
||||
size = p - buf;
|
||||
}
|
||||
}
|
||||
|
||||
if(force_gmt) {
|
||||
*p++ = 0x5a; /* "Z" */
|
||||
*p++ = 0;
|
||||
size++;
|
||||
} else {
|
||||
int ret;
|
||||
gmtoff %= 86400;
|
||||
ret = snprintf(p, buf_size - size, "%+03ld%02ld",
|
||||
gmtoff / 3600, labs(gmtoff % 3600) / 60);
|
||||
if(ret != 5) {
|
||||
FREEMEM(buf);
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
size += ret;
|
||||
}
|
||||
|
||||
if(opt_gt) {
|
||||
if(opt_gt->buf)
|
||||
FREEMEM(opt_gt->buf);
|
||||
} else {
|
||||
opt_gt = (GeneralizedTime_t *)CALLOC(1, sizeof *opt_gt);
|
||||
if(!opt_gt) { FREEMEM(buf); return 0; }
|
||||
}
|
||||
|
||||
opt_gt->buf = (unsigned char *)buf;
|
||||
opt_gt->size = size;
|
||||
|
||||
return opt_gt;
|
||||
}
|
||||
|
||||
int
|
||||
GeneralizedTime_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
|
||||
const void *bptr) {
|
||||
const GeneralizedTime_t *a = aptr;
|
||||
const GeneralizedTime_t *b = bptr;
|
||||
|
||||
(void)td;
|
||||
|
||||
if(a && b) {
|
||||
int afrac_value, afrac_digits;
|
||||
int bfrac_value, bfrac_digits;
|
||||
int aerr, berr;
|
||||
time_t at, bt;
|
||||
|
||||
errno = EPERM;
|
||||
at = asn_GT2time_frac(a, &afrac_value, &afrac_digits, 0, 0);
|
||||
aerr = errno;
|
||||
errno = EPERM;
|
||||
bt = asn_GT2time_frac(b, &bfrac_value, &bfrac_digits, 0, 0);
|
||||
berr = errno;
|
||||
|
||||
if(at == -1 && aerr != EPERM) {
|
||||
if(bt == -1 && berr != EPERM) {
|
||||
return OCTET_STRING_compare(td, aptr, bptr);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if(bt == -1 && berr != EPERM) {
|
||||
return 1;
|
||||
} else {
|
||||
/* Both values are valid. */
|
||||
}
|
||||
|
||||
if(at < bt) {
|
||||
return -1;
|
||||
} else if(at > bt) {
|
||||
return 1;
|
||||
} else if(afrac_digits == bfrac_digits) {
|
||||
if(afrac_value == bfrac_value) {
|
||||
return 0;
|
||||
}
|
||||
if(afrac_value < bfrac_value) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if(afrac_digits == 0) {
|
||||
return -1;
|
||||
} else if(bfrac_digits == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
double afrac = (double)afrac_value / afrac_digits;
|
||||
double bfrac = (double)bfrac_value / bfrac_digits;
|
||||
if(afrac < bfrac) {
|
||||
return -1;
|
||||
} else if(afrac > bfrac) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if(!a && !b) {
|
||||
return 0;
|
||||
} else if(!a) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _GeneralizedTime_H_
|
||||
#define _GeneralizedTime_H_
|
||||
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t GeneralizedTime_t; /* Implemented via OCTET STRING */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_GeneralizedTime;
|
||||
extern asn_TYPE_operation_t asn_OP_GeneralizedTime;
|
||||
|
||||
#define GeneralizedTime_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f GeneralizedTime_print;
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f GeneralizedTime_compare;
|
||||
#define GeneralizedTime_copy OCTET_STRING_copy
|
||||
|
||||
asn_constr_check_f GeneralizedTime_constraint;
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define GeneralizedTime_decode_ber OCTET_STRING_decode_ber
|
||||
der_type_encoder_f GeneralizedTime_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define GeneralizedTime_decode_xer OCTET_STRING_decode_xer_utf8
|
||||
xer_type_encoder_f GeneralizedTime_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
#define GeneralizedTime_decode_jer OCTET_STRING_decode_jer_utf8
|
||||
jer_type_encoder_f GeneralizedTime_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
#define GeneralizedTime_decode_uper OCTET_STRING_decode_uper
|
||||
#define GeneralizedTime_encode_uper OCTET_STRING_encode_uper
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define GeneralizedTime_decode_aper OCTET_STRING_decode_aper
|
||||
#define GeneralizedTime_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f GeneralizedTime_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
/***********************
|
||||
* Some handy helpers. *
|
||||
***********************/
|
||||
|
||||
struct tm; /* <time.h> */
|
||||
|
||||
/*
|
||||
* Convert a GeneralizedTime structure into time_t
|
||||
* and optionally into struct tm.
|
||||
* If as_gmt is given, the resulting _optional_tm4fill will have a GMT zone,
|
||||
* instead of default local one.
|
||||
* On error returns -1 and errno set to EINVAL
|
||||
*/
|
||||
time_t asn_GT2time(const GeneralizedTime_t *, struct tm *_optional_tm4fill,
|
||||
int as_gmt);
|
||||
|
||||
/* A version of the above function also returning the fractions of seconds */
|
||||
time_t asn_GT2time_frac(const GeneralizedTime_t *,
|
||||
int *frac_value, int *frac_digits, /* (value / (10 ^ digits)) */
|
||||
struct tm *_optional_tm4fill, int as_gmt);
|
||||
|
||||
/*
|
||||
* Another version returning fractions with defined precision
|
||||
* For example, parsing of the time ending with ".1" seconds
|
||||
* with frac_digits=3 (msec) would yield frac_value = 100.
|
||||
*/
|
||||
time_t asn_GT2time_prec(const GeneralizedTime_t *,
|
||||
int *frac_value, int frac_digits,
|
||||
struct tm *_optional_tm4fill, int as_gmt);
|
||||
|
||||
/*
|
||||
* Convert a struct tm into GeneralizedTime.
|
||||
* If _optional_gt is not given, this function will try to allocate one.
|
||||
* If force_gmt is given, the resulting GeneralizedTime will be forced
|
||||
* into a GMT time zone (encoding ends with a "Z").
|
||||
* On error, this function returns 0 and sets errno.
|
||||
*/
|
||||
GeneralizedTime_t *asn_time2GT(GeneralizedTime_t *_optional_gt,
|
||||
const struct tm *, int force_gmt);
|
||||
GeneralizedTime_t *asn_time2GT_frac(GeneralizedTime_t *_optional_gt,
|
||||
const struct tm *, int frac_value, int frac_digits, int force_gmt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GeneralizedTime_H_ */
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralizedTime.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "/usr/include/time.h"
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
asn_enc_rval_t
|
||||
GeneralizedTime_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
GeneralizedTime_t *st;
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
int fv, fd; /* seconds fraction value and number of digits */
|
||||
struct tm tm;
|
||||
time_t tloc;
|
||||
|
||||
/*
|
||||
* Encode as a canonical DER.
|
||||
*/
|
||||
errno = EPERM;
|
||||
tloc = asn_GT2time_frac((const GeneralizedTime_t *)sptr, &fv, &fd, &tm,
|
||||
1); /* Recognize time */
|
||||
if(tloc == -1 && errno != EPERM) {
|
||||
/* Failed to recognize time. Fail completely. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
st = asn_time2GT_frac(0, &tm, fv, fd, 1); /* Save time canonically */
|
||||
if(!st) ASN__ENCODE_FAILED; /* Memory allocation failure. */
|
||||
|
||||
erval = OCTET_STRING_encode_der(td, st, tag_mode, tag, cb, app_key);
|
||||
|
||||
ASN_STRUCT_FREE(*td, st);
|
||||
|
||||
return erval;
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralizedTime.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "/usr/include/time.h"
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined(ASN___INTERNAL_TEST_MODE)
|
||||
asn_enc_rval_t
|
||||
GeneralizedTime_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel,
|
||||
enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
GeneralizedTime_t *gt;
|
||||
asn_enc_rval_t rv;
|
||||
int fv, fd; /* fractional parts */
|
||||
struct tm tm;
|
||||
|
||||
errno = EPERM;
|
||||
if(asn_GT2time_frac((const GeneralizedTime_t *)sptr,
|
||||
&fv, &fd, &tm, 1) == -1
|
||||
&& errno != EPERM)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
gt = asn_time2GT_frac(0, &tm, fv, fd, 1);
|
||||
if(!gt) ASN__ENCODE_FAILED;
|
||||
|
||||
rv = OCTET_STRING_encode_jer_utf8(td, constraints, sptr, ilevel, flags,
|
||||
cb, app_key);
|
||||
ASN_STRUCT_FREE(asn_DEF_GeneralizedTime, gt);
|
||||
return rv;
|
||||
}
|
||||
#endif /* !defined(ASN___INTERNAL_TEST_MODE) */
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralizedTime.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "/usr/include/time.h"
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
int
|
||||
GeneralizedTime_print(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const GeneralizedTime_t *st = (const GeneralizedTime_t *)sptr;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(st && st->buf) {
|
||||
char buf[32];
|
||||
struct tm tm;
|
||||
int ret;
|
||||
|
||||
errno = EPERM;
|
||||
if(asn_GT2time(st, &tm, 1) == -1 && errno != EPERM)
|
||||
return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf),
|
||||
"%04d-%02d-%02d %02d:%02d:%02d (GMT)",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
assert(ret > 0 && ret < (int)sizeof(buf));
|
||||
return (cb(buf, ret, app_key) < 0) ? -1 : 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralizedTime.h"
|
||||
|
||||
asn_random_fill_result_t
|
||||
GeneralizedTime_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
static const char *values[] = {
|
||||
"19700101000000", "19700101000000-0000", "19700101000000+0000",
|
||||
"19700101000000Z", "19700101000000.3Z", "19821106210623.3",
|
||||
"19821106210629.3Z", "19691106210827.3-0500", "19821106210629.456",
|
||||
};
|
||||
size_t rnd = asn_random_between(0, sizeof(values)/sizeof(values[0])-1);
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(max_length < sizeof("yyyymmddhhmmss") && !*sptr) {
|
||||
return result_skipped;
|
||||
}
|
||||
|
||||
if(*sptr) {
|
||||
if(OCTET_STRING_fromBuf(*sptr, values[rnd], -1) != 0) {
|
||||
if(!sptr) return result_failed;
|
||||
}
|
||||
} else {
|
||||
*sptr = OCTET_STRING_new_fromBuf(td, values[rnd], -1);
|
||||
if(!sptr) return result_failed;
|
||||
}
|
||||
|
||||
return result_ok;
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GeneralizedTime.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "/usr/include/time.h"
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined(ASN___INTERNAL_TEST_MODE)
|
||||
asn_enc_rval_t
|
||||
GeneralizedTime_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
if(flags & XER_F_CANONICAL) {
|
||||
GeneralizedTime_t *gt;
|
||||
asn_enc_rval_t rv;
|
||||
int fv, fd; /* fractional parts */
|
||||
struct tm tm;
|
||||
|
||||
errno = EPERM;
|
||||
if(asn_GT2time_frac((const GeneralizedTime_t *)sptr,
|
||||
&fv, &fd, &tm, 1) == -1
|
||||
&& errno != EPERM)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
gt = asn_time2GT_frac(0, &tm, fv, fd, 1);
|
||||
if(!gt) ASN__ENCODE_FAILED;
|
||||
|
||||
rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
|
||||
cb, app_key);
|
||||
ASN_STRUCT_FREE(asn_DEF_GeneralizedTime, gt);
|
||||
return rv;
|
||||
} else {
|
||||
return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
|
||||
cb, app_key);
|
||||
}
|
||||
}
|
||||
#endif /* !defined(ASN___INTERNAL_TEST_MODE) */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "GraphicString.h"
|
||||
|
||||
/*
|
||||
* GraphicString basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_GraphicString_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (25 << 2)), /* [UNIVERSAL 25] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_GraphicString = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
OCTET_STRING_print, /* non-ascii string */
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_hex,
|
||||
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_hex,
|
||||
OCTET_STRING_encode_jer, /* Can't expect it to be ASCII/UTF8 */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
OCTET_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_GraphicString = {
|
||||
"GraphicString",
|
||||
"GraphicString",
|
||||
&asn_OP_GraphicString,
|
||||
asn_DEF_GraphicString_tags,
|
||||
sizeof(asn_DEF_GraphicString_tags)
|
||||
/ sizeof(asn_DEF_GraphicString_tags[0]) - 1,
|
||||
asn_DEF_GraphicString_tags,
|
||||
sizeof(asn_DEF_GraphicString_tags)
|
||||
/ sizeof(asn_DEF_GraphicString_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_unknown_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _GraphicString_H_
|
||||
#define _GraphicString_H_
|
||||
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t GraphicString_t; /* Implemented via OCTET STRING */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_GraphicString;
|
||||
extern asn_TYPE_operation_t asn_OP_GraphicString;
|
||||
|
||||
#define GraphicString_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define GraphicString_print OCTET_STRING_print
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define GraphicString_compare OCTET_STRING_compare
|
||||
#define GraphicString_copy OCTET_STRING_copy
|
||||
|
||||
#define GraphicString_constraint asn_generic_unknown_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define GraphicString_decode_ber OCTET_STRING_decode_ber
|
||||
#define GraphicString_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define GraphicString_decode_xer OCTET_STRING_decode_xer_hex
|
||||
#define GraphicString_encode_xer OCTET_STRING_encode_xer
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
#define GraphicString_decode_jer OCTET_STRING_decode_jer
|
||||
#define GraphicString_encode_jer OCTET_STRING_encode_jer
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
#define GraphicString_decode_uper OCTET_STRING_decode_uper
|
||||
#define GraphicString_encode_uper OCTET_STRING_encode_uper
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define GraphicString_decode_aper OCTET_STRING_decode_aper
|
||||
#define GraphicString_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GraphicString_H_ */
|
||||
@@ -0,0 +1,139 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "IA5String.h"
|
||||
|
||||
/*
|
||||
* IA5String basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_IA5String_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), /* [UNIVERSAL 22] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
static asn_per_constraints_t asn_DEF_IA5String_per_constraints = {
|
||||
{ APC_CONSTRAINED, 7, 7, 0, 0x7f }, /* Value */
|
||||
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
|
||||
0, 0
|
||||
};
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
asn_TYPE_operation_t asn_OP_IA5String = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
OCTET_STRING_print_utf8, /* ASCII subset */
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_utf8,
|
||||
OCTET_STRING_encode_xer_utf8,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_utf8,
|
||||
OCTET_STRING_encode_jer_utf8,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper,
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper,
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
OCTET_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_IA5String = {
|
||||
"IA5String",
|
||||
"IA5String",
|
||||
&asn_OP_IA5String,
|
||||
asn_DEF_IA5String_tags,
|
||||
sizeof(asn_DEF_IA5String_tags)
|
||||
/ sizeof(asn_DEF_IA5String_tags[0]) - 1,
|
||||
asn_DEF_IA5String_tags,
|
||||
sizeof(asn_DEF_IA5String_tags)
|
||||
/ sizeof(asn_DEF_IA5String_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
&asn_DEF_IA5String_per_constraints,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
IA5String_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
int
|
||||
IA5String_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const IA5String_t *st = (const IA5String_t *)sptr;
|
||||
|
||||
if(st && st->buf) {
|
||||
uint8_t *buf = st->buf;
|
||||
uint8_t *end = buf + st->size;
|
||||
/*
|
||||
* IA5String is generally equivalent to 7bit ASCII.
|
||||
* ISO/ITU-T T.50, 1963.
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
if(*buf > 0x7F) {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: value byte %ld out of range: "
|
||||
"%d > 127 (%s:%d)",
|
||||
td->name,
|
||||
(long)((buf - st->buf) + 1),
|
||||
*buf,
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: value not given (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _IA5String_H_
|
||||
#define _IA5String_H_
|
||||
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t IA5String_t; /* Implemented via OCTET STRING */
|
||||
|
||||
/*
|
||||
* IA5String ASN.1 type definition.
|
||||
*/
|
||||
extern asn_TYPE_descriptor_t asn_DEF_IA5String;
|
||||
extern asn_TYPE_operation_t asn_OP_IA5String;
|
||||
|
||||
#define IA5String_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define IA5String_print OCTET_STRING_print_utf8
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define IA5String_compare OCTET_STRING_compare
|
||||
#define IA5String_copy OCTET_STRING_copy
|
||||
|
||||
asn_constr_check_f IA5String_constraint;
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define IA5String_decode_ber OCTET_STRING_decode_ber
|
||||
#define IA5String_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define IA5String_decode_xer OCTET_STRING_decode_xer_utf8
|
||||
#define IA5String_encode_xer OCTET_STRING_encode_xer_utf8
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
#define IA5String_decode_jer OCTET_STRING_decode_jer_utf8
|
||||
#define IA5String_encode_jer OCTET_STRING_encode_jer_utf8
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
#define IA5String_decode_uper OCTET_STRING_decode_uper
|
||||
#define IA5String_encode_uper OCTET_STRING_encode_uper
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define IA5String_decode_aper OCTET_STRING_decode_aper
|
||||
#define IA5String_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IA5String_H_ */
|
||||
@@ -0,0 +1,826 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2019 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
* INTEGER basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_INTEGER = {
|
||||
INTEGER_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
INTEGER_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
INTEGER_compare,
|
||||
INTEGER_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_decode_primitive,
|
||||
INTEGER_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
INTEGER_decode_xer,
|
||||
INTEGER_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
INTEGER_decode_jer,
|
||||
INTEGER_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
INTEGER_decode_oer, /* OER decoder */
|
||||
INTEGER_encode_oer, /* Canonical OER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
INTEGER_decode_uper, /* Unaligned PER decoder */
|
||||
INTEGER_encode_uper, /* Unaligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
INTEGER_decode_aper, /* Aligned PER decoder */
|
||||
INTEGER_encode_aper, /* Aligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
INTEGER_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_INTEGER = {
|
||||
"INTEGER",
|
||||
"INTEGER",
|
||||
&asn_OP_INTEGER,
|
||||
asn_DEF_INTEGER_tags,
|
||||
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
|
||||
asn_DEF_INTEGER_tags, /* Same as above */
|
||||
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
/*
|
||||
* INTEGER specific human-readable output.
|
||||
*/
|
||||
ssize_t
|
||||
INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXEROrJER) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
char scratch[32];
|
||||
uint8_t *buf = st->buf;
|
||||
uint8_t *buf_end = st->buf + st->size;
|
||||
intmax_t value = 0;
|
||||
ssize_t wrote = 0;
|
||||
char *p = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if(specs && specs->field_unsigned)
|
||||
ret = asn_INTEGER2umax(st, (uintmax_t *)&value);
|
||||
else
|
||||
ret = asn_INTEGER2imax(st, &value);
|
||||
|
||||
/* Simple case: the integer size is small */
|
||||
if(ret == 0) {
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
el = (value >= 0 || !specs || !specs->field_unsigned)
|
||||
? INTEGER_map_value2enum(specs, value) : 0;
|
||||
if(el) {
|
||||
if(plainOrXEROrJER == 0)
|
||||
return asn__format_to_callback(cb, app_key,
|
||||
"%" ASN_PRIdMAX " (%s)", value, el->enum_name);
|
||||
else if (plainOrXEROrJER == 1)
|
||||
return asn__format_to_callback(cb, app_key,
|
||||
"<%s/>", el->enum_name);
|
||||
else if (plainOrXEROrJER == 2)
|
||||
return asn__format_to_callback(cb, app_key,
|
||||
"\"%s\"", el->enum_name);
|
||||
} else if(plainOrXEROrJER && specs && specs->strict_enumeration) {
|
||||
ASN_DEBUG("ASN.1 forbids dealing with "
|
||||
"unknown value of ENUMERATED type");
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
} else {
|
||||
return asn__format_to_callback(cb, app_key,
|
||||
(specs && specs->field_unsigned)
|
||||
? "%" ASN_PRIuMAX
|
||||
: "%" ASN_PRIdMAX,
|
||||
value);
|
||||
}
|
||||
} else if(plainOrXEROrJER && specs && specs->strict_enumeration) {
|
||||
/*
|
||||
* Here and earlier, we cannot encode the ENUMERATED values
|
||||
* if there is no corresponding identifier.
|
||||
*/
|
||||
ASN_DEBUG("ASN.1 forbids dealing with "
|
||||
"unknown value of ENUMERATED type");
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Output in the long xx:yy:zz... format */
|
||||
/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
|
||||
|
||||
/* For JER (JSON), large integers should be quoted as strings */
|
||||
if(plainOrXEROrJER == 2) {
|
||||
if(cb("\"", 1, app_key) < 0) return -1;
|
||||
wrote += 1;
|
||||
}
|
||||
|
||||
for(p = scratch; buf < buf_end; buf++) {
|
||||
const char * const h2c = "0123456789ABCDEF";
|
||||
if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
|
||||
/* Flush buffer */
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
wrote += p - scratch;
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = h2c[*buf >> 4];
|
||||
*p++ = h2c[*buf & 0x0F];
|
||||
*p++ = 0x3a; /* ":" */
|
||||
}
|
||||
if(p != scratch)
|
||||
p--; /* Remove the last ":" */
|
||||
|
||||
wrote += p - scratch;
|
||||
if((cb(scratch, p - scratch, app_key) < 0)) return -1;
|
||||
|
||||
/* Close quote for JER (JSON) */
|
||||
if(plainOrXEROrJER == 2) {
|
||||
if(cb("\"", 1, app_key) < 0) return -1;
|
||||
wrote += 1;
|
||||
}
|
||||
|
||||
return wrote;
|
||||
}
|
||||
|
||||
static int
|
||||
INTEGER__compar_value2enum(const void *kp, const void *am) {
|
||||
long a = *(const long *)kp;
|
||||
const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
|
||||
long b = el->nat_value;
|
||||
if(a < b) return -1;
|
||||
else if(a == b) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
const asn_INTEGER_enum_map_t *
|
||||
INTEGER_map_value2enum(const asn_INTEGER_specifics_t *specs, long value) {
|
||||
int count = specs ? specs->map_count : 0;
|
||||
if(!count) return 0;
|
||||
return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
|
||||
count, sizeof(specs->value2enum[0]),
|
||||
INTEGER__compar_value2enum);
|
||||
}
|
||||
|
||||
static intmax_t
|
||||
asn__integer_convert(const uint8_t *b, const uint8_t *end) {
|
||||
uintmax_t value;
|
||||
|
||||
/* Perform the sign initialization */
|
||||
/* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
|
||||
if((*b >> 7)) {
|
||||
value = (uintmax_t)(-1);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
/* Conversion engine */
|
||||
for(; b < end; b++) {
|
||||
value = (value << 8) | *b;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {
|
||||
uint8_t *b, *end;
|
||||
size_t size = 0;
|
||||
|
||||
/* Sanity checking */
|
||||
if(!iptr || !iptr->buf || !lptr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Cache the begin/end of the buffer */
|
||||
b = iptr->buf; /* Start of the INTEGER buffer */
|
||||
size = iptr->size;
|
||||
end = b + size; /* Where to stop */
|
||||
|
||||
if(size > sizeof(intmax_t)) {
|
||||
uint8_t *end1 = end - 1;
|
||||
/*
|
||||
* Slightly more advanced processing,
|
||||
* able to process INTEGERs with >sizeof(intmax_t) bytes
|
||||
* when the actual value is small, e.g. for intmax_t == int32_t
|
||||
* (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)
|
||||
*/
|
||||
/* Skip out the insignificant leading bytes */
|
||||
for(; b < end1; b++) {
|
||||
switch(*b) {
|
||||
case 0x00: if((b[1] & 0x80) == 0) continue; break;
|
||||
case 0xff: if((b[1] & 0x80) != 0) continue; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
size = end - b;
|
||||
if(size > sizeof(intmax_t)) {
|
||||
/* Still cannot fit the sizeof(intmax_t) */
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shortcut processing of a corner case */
|
||||
if(end == b) {
|
||||
*lptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*lptr = asn__integer_convert(b, end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */
|
||||
int
|
||||
asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {
|
||||
uint8_t *b, *end;
|
||||
uintmax_t value;
|
||||
size_t size;
|
||||
|
||||
if(!iptr || !iptr->buf || !lptr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
b = iptr->buf;
|
||||
size = iptr->size;
|
||||
end = b + size;
|
||||
|
||||
/* If all extra leading bytes are zeroes, ignore them */
|
||||
for(; size > sizeof(value); b++, size--) {
|
||||
if(*b) {
|
||||
/* Value won't fit into uintmax_t */
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Conversion engine */
|
||||
for(value = 0; b < end; b++)
|
||||
value = (value << 8) | *b;
|
||||
|
||||
*lptr = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
uint8_t *b;
|
||||
int shr;
|
||||
|
||||
if(value <= ((~(uintmax_t)0) >> 1)) {
|
||||
return asn_imax2INTEGER(st, value);
|
||||
}
|
||||
|
||||
buf = (uint8_t *)MALLOC(1 + sizeof(value));
|
||||
if(!buf) return -1;
|
||||
|
||||
end = buf + (sizeof(value) + 1);
|
||||
buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */
|
||||
for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)
|
||||
*b = (uint8_t)(value >> shr);
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = 1 + sizeof(value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {
|
||||
uint8_t *buf, *bp;
|
||||
volatile uint8_t *p;
|
||||
volatile uint8_t *pstart;
|
||||
volatile uint8_t *pend1;
|
||||
int littleEndian = 1; /* Run-time detection */
|
||||
volatile int add;
|
||||
|
||||
if(!st) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = (uint8_t *)(long *)MALLOC(sizeof(value));
|
||||
if(!buf) return -1;
|
||||
|
||||
if(*(char *)&littleEndian) {
|
||||
pstart = (uint8_t *)&value + sizeof(value) - 1;
|
||||
pend1 = (uint8_t *)&value;
|
||||
add = -1;
|
||||
} else {
|
||||
pstart = (uint8_t *)&value;
|
||||
pend1 = pstart + sizeof(value) - 1;
|
||||
add = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the contents octet consists of more than one octet,
|
||||
* then bits of the first octet and bit 8 of the second octet:
|
||||
* a) shall not all be ones; and
|
||||
* b) shall not all be zero.
|
||||
*/
|
||||
for(p = pstart; p != pend1; p += add) {
|
||||
switch(*p) {
|
||||
case 0x00: if((*(p+add) & 0x80) == 0)
|
||||
continue;
|
||||
break;
|
||||
case 0xff: if((*(p+add) & 0x80))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Copy the integer body */
|
||||
for(bp = buf, pend1 += add; p != pend1; p += add)
|
||||
*bp++ = *p;
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = bp - buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
asn_INTEGER2long(const INTEGER_t *iptr, long *l) {
|
||||
intmax_t v;
|
||||
if(asn_INTEGER2imax(iptr, &v) == 0) {
|
||||
if(v < LONG_MIN || v > LONG_MAX) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
*l = v;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {
|
||||
uintmax_t v;
|
||||
if(asn_INTEGER2umax(iptr, &v) == 0) {
|
||||
if(v > ULONG_MAX) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
*l = v;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
asn_long2INTEGER(INTEGER_t *st, long value) {
|
||||
return asn_imax2INTEGER(st, value);
|
||||
}
|
||||
|
||||
int
|
||||
asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
|
||||
return asn_imax2INTEGER(st, value);
|
||||
}
|
||||
|
||||
int asn_INTEGER2int64(const INTEGER_t *st, int64_t *value) {
|
||||
intmax_t v;
|
||||
if(asn_INTEGER2imax(st, &v) == 0) {
|
||||
if(v < INT64_MIN || v > INT64_MAX) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
*value = v;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn_INTEGER2uint64(const INTEGER_t *st, uint64_t *value) {
|
||||
uintmax_t v;
|
||||
if(asn_INTEGER2umax(st, &v) == 0) {
|
||||
if(v > UINT64_MAX) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
*value = v;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
uint8_t *b;
|
||||
int shr;
|
||||
|
||||
if(value <= INT64_MAX)
|
||||
return asn_int642INTEGER(st, value);
|
||||
|
||||
buf = (uint8_t *)MALLOC(1 + sizeof(value));
|
||||
if(!buf) return -1;
|
||||
|
||||
end = buf + (sizeof(value) + 1);
|
||||
buf[0] = 0;
|
||||
for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)
|
||||
*b = (uint8_t)(value >> shr);
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = 1 + sizeof(value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
asn_int642INTEGER(INTEGER_t *st, int64_t value) {
|
||||
uint8_t *buf, *bp;
|
||||
volatile uint8_t *p;
|
||||
volatile uint8_t *pstart;
|
||||
volatile uint8_t *pend1;
|
||||
int littleEndian = 1; /* Run-time detection */
|
||||
volatile int add;
|
||||
|
||||
if(!st) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = (uint8_t *)MALLOC(sizeof(value));
|
||||
if(!buf) return -1;
|
||||
|
||||
if(*(char *)&littleEndian) {
|
||||
pstart = (uint8_t *)&value + sizeof(value) - 1;
|
||||
pend1 = (uint8_t *)&value;
|
||||
add = -1;
|
||||
} else {
|
||||
pstart = (uint8_t *)&value;
|
||||
pend1 = pstart + sizeof(value) - 1;
|
||||
add = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the contents octet consists of more than one octet,
|
||||
* then bits of the first octet and bit 8 of the second octet:
|
||||
* a) shall not all be ones; and
|
||||
* b) shall not all be zero.
|
||||
*/
|
||||
for(p = pstart; p != pend1; p += add) {
|
||||
switch(*p) {
|
||||
case 0x00: if((*(p+add) & 0x80) == 0)
|
||||
continue;
|
||||
break;
|
||||
case 0xff: if((*(p+add) & 0x80))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Copy the integer body */
|
||||
for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
|
||||
*bp++ = *p;
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = bp - buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the number in the given string until the given *end position,
|
||||
* returning the position after the last parsed character back using the
|
||||
* same (*end) pointer.
|
||||
* WARNING: This behavior is different from the standard strtol/strtoimax(3).
|
||||
*/
|
||||
enum asn_strtox_result_e
|
||||
asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
|
||||
int sign = 1;
|
||||
intmax_t value;
|
||||
|
||||
const intmax_t asn1_intmax_max = ((~(uintmax_t)0) >> 1);
|
||||
const intmax_t upper_boundary = asn1_intmax_max / 10;
|
||||
intmax_t last_digit_max = asn1_intmax_max % 10;
|
||||
|
||||
if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
|
||||
|
||||
switch(*str) {
|
||||
case '-':
|
||||
last_digit_max++;
|
||||
sign = -1;
|
||||
/* FALL THROUGH */
|
||||
case '+':
|
||||
str++;
|
||||
if(str >= *end) {
|
||||
*end = str;
|
||||
return ASN_STRTOX_EXPECT_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
for(value = 0; str < (*end); str++) {
|
||||
if(*str >= 0x30 && *str <= 0x39) {
|
||||
int d = *str - '0';
|
||||
if(value < upper_boundary) {
|
||||
value = value * 10 + d;
|
||||
} else if(value == upper_boundary) {
|
||||
if(d <= last_digit_max) {
|
||||
if(sign > 0) {
|
||||
value = value * 10 + d;
|
||||
} else {
|
||||
sign = 1;
|
||||
value = -value * 10 - d;
|
||||
}
|
||||
str += 1;
|
||||
if(str < *end) {
|
||||
// If digits continue, we're guaranteed out of range.
|
||||
*end = str;
|
||||
if(*str >= 0x30 && *str <= 0x39) {
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
} else {
|
||||
*intp = sign * value;
|
||||
return ASN_STRTOX_EXTRA_DATA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
*end = str;
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
} else {
|
||||
*end = str;
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
} else {
|
||||
*end = str;
|
||||
*intp = sign * value;
|
||||
return ASN_STRTOX_EXTRA_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
*end = str;
|
||||
*intp = sign * value;
|
||||
return ASN_STRTOX_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the number in the given string until the given *end position,
|
||||
* returning the position after the last parsed character back using the
|
||||
* same (*end) pointer.
|
||||
* WARNING: This behavior is different from the standard strtoul/strtoumax(3).
|
||||
*/
|
||||
enum asn_strtox_result_e
|
||||
asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {
|
||||
uintmax_t value;
|
||||
|
||||
const uintmax_t asn1_uintmax_max = ((~(uintmax_t)0));
|
||||
const uintmax_t upper_boundary = asn1_uintmax_max / 10;
|
||||
uintmax_t last_digit_max = asn1_uintmax_max % 10;
|
||||
|
||||
if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
|
||||
|
||||
switch(*str) {
|
||||
case '-':
|
||||
return ASN_STRTOX_ERROR_INVAL;
|
||||
case '+':
|
||||
str++;
|
||||
if(str >= *end) {
|
||||
*end = str;
|
||||
return ASN_STRTOX_EXPECT_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
for(value = 0; str < (*end); str++) {
|
||||
if(*str >= 0x30 && *str <= 0x39) {
|
||||
unsigned int d = *str - '0';
|
||||
if(value < upper_boundary) {
|
||||
value = value * 10 + d;
|
||||
} else if(value == upper_boundary) {
|
||||
if(d <= last_digit_max) {
|
||||
value = value * 10 + d;
|
||||
str += 1;
|
||||
if(str < *end) {
|
||||
// If digits continue, we're guaranteed out of range.
|
||||
*end = str;
|
||||
if(*str >= 0x30 && *str <= 0x39) {
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
} else {
|
||||
*uintp = value;
|
||||
return ASN_STRTOX_EXTRA_DATA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
*end = str;
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
} else {
|
||||
*end = str;
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
} else {
|
||||
*end = str;
|
||||
*uintp = value;
|
||||
return ASN_STRTOX_EXTRA_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
*end = str;
|
||||
*uintp = value;
|
||||
return ASN_STRTOX_OK;
|
||||
}
|
||||
|
||||
enum asn_strtox_result_e
|
||||
asn_strtol_lim(const char *str, const char **end, long *lp) {
|
||||
intmax_t value;
|
||||
switch(asn_strtoimax_lim(str, end, &value)) {
|
||||
case ASN_STRTOX_ERROR_RANGE:
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
case ASN_STRTOX_ERROR_INVAL:
|
||||
return ASN_STRTOX_ERROR_INVAL;
|
||||
case ASN_STRTOX_EXPECT_MORE:
|
||||
return ASN_STRTOX_EXPECT_MORE;
|
||||
case ASN_STRTOX_OK:
|
||||
if(value >= LONG_MIN && value <= LONG_MAX) {
|
||||
*lp = value;
|
||||
return ASN_STRTOX_OK;
|
||||
} else {
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
case ASN_STRTOX_EXTRA_DATA:
|
||||
if(value >= LONG_MIN && value <= LONG_MAX) {
|
||||
*lp = value;
|
||||
return ASN_STRTOX_EXTRA_DATA;
|
||||
} else {
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!"Unreachable");
|
||||
return ASN_STRTOX_ERROR_INVAL;
|
||||
}
|
||||
|
||||
enum asn_strtox_result_e
|
||||
asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {
|
||||
uintmax_t value;
|
||||
switch(asn_strtoumax_lim(str, end, &value)) {
|
||||
case ASN_STRTOX_ERROR_RANGE:
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
case ASN_STRTOX_ERROR_INVAL:
|
||||
return ASN_STRTOX_ERROR_INVAL;
|
||||
case ASN_STRTOX_EXPECT_MORE:
|
||||
return ASN_STRTOX_EXPECT_MORE;
|
||||
case ASN_STRTOX_OK:
|
||||
if(value <= ULONG_MAX) {
|
||||
*ulp = value;
|
||||
return ASN_STRTOX_OK;
|
||||
} else {
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
case ASN_STRTOX_EXTRA_DATA:
|
||||
if(value <= ULONG_MAX) {
|
||||
*ulp = value;
|
||||
return ASN_STRTOX_EXTRA_DATA;
|
||||
} else {
|
||||
return ASN_STRTOX_ERROR_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!"Unreachable");
|
||||
return ASN_STRTOX_ERROR_INVAL;
|
||||
}
|
||||
|
||||
int
|
||||
INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
|
||||
const void *bptr) {
|
||||
const INTEGER_t *a = aptr;
|
||||
const INTEGER_t *b = bptr;
|
||||
|
||||
(void)td;
|
||||
|
||||
if(a && b) {
|
||||
if(a->size && b->size) {
|
||||
int sign_a = (a->buf[0] & 0x80) ? -1 : 1;
|
||||
int sign_b = (b->buf[0] & 0x80) ? -1 : 1;
|
||||
|
||||
if(sign_a < sign_b) return -1;
|
||||
if(sign_a > sign_b) return 1;
|
||||
|
||||
/* The shortest integer wins, unless comparing negatives */
|
||||
if(a->size < b->size) {
|
||||
return -1 * sign_a;
|
||||
} else if(a->size > b->size) {
|
||||
return 1 * sign_b;
|
||||
}
|
||||
|
||||
return sign_a * memcmp(a->buf, b->buf, a->size);
|
||||
} else if(a->size) {
|
||||
int sign = (a->buf[0] & 0x80) ? -1 : 1;
|
||||
return (1) * sign;
|
||||
} else if(b->size) {
|
||||
int sign = (a->buf[0] & 0x80) ? -1 : 1;
|
||||
return (-1) * sign;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if(!a && !b) {
|
||||
return 0;
|
||||
} else if(!a) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
INTEGER_copy(const asn_TYPE_descriptor_t *td, void **aptr,
|
||||
const void *bptr) {
|
||||
(void)td;
|
||||
INTEGER_t *a = *aptr;
|
||||
const INTEGER_t *b = bptr;
|
||||
|
||||
if(!b) {
|
||||
if(a) {
|
||||
FREEMEM(a->buf);
|
||||
FREEMEM(a);
|
||||
*aptr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!a) {
|
||||
a = *aptr = CALLOC(1, sizeof(*a));
|
||||
if(!a) return -1;
|
||||
}
|
||||
|
||||
if(b->size) {
|
||||
uint8_t* buf = MALLOC(b->size);
|
||||
if(!buf) return -1;
|
||||
memcpy(buf, b->buf, b->size);
|
||||
FREEMEM(a->buf);
|
||||
a->buf = buf;
|
||||
a->size = b->size;
|
||||
} else {
|
||||
FREEMEM(a->buf);
|
||||
a->buf = 0;
|
||||
a->size = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _INTEGER_H_
|
||||
#define _INTEGER_H_
|
||||
|
||||
#include "asn_application.h"
|
||||
#include "asn_codecs_prim.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
|
||||
extern asn_TYPE_operation_t asn_OP_INTEGER;
|
||||
|
||||
/* Map with <tag> to integer value association */
|
||||
typedef struct asn_INTEGER_enum_map_s {
|
||||
long nat_value; /* associated native integer value */
|
||||
size_t enum_len; /* strlen("tag") */
|
||||
const char *enum_name; /* "tag" */
|
||||
} asn_INTEGER_enum_map_t;
|
||||
|
||||
/* This type describes an enumeration for INTEGER and ENUMERATED types */
|
||||
typedef struct asn_INTEGER_specifics_s {
|
||||
const asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */
|
||||
const unsigned int *enum2value; /* "tag" => N; sorted by tag */
|
||||
int map_count; /* Elements in either map */
|
||||
int extension; /* This map is extensible */
|
||||
int strict_enumeration; /* Enumeration set is fixed */
|
||||
int field_width; /* Size of native integer */
|
||||
int field_unsigned; /* Signed=0, unsigned=1 */
|
||||
} asn_INTEGER_specifics_t;
|
||||
|
||||
ssize_t INTEGER__dump(const asn_TYPE_descriptor_t *td,
|
||||
const INTEGER_t *st,
|
||||
asn_app_consume_bytes_f *cb,
|
||||
void *app_key, int plainOrXER);
|
||||
|
||||
#define INTEGER_free ASN__PRIMITIVE_TYPE_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f INTEGER_print;
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f INTEGER_compare;
|
||||
asn_struct_copy_f INTEGER_copy;
|
||||
|
||||
#define INTEGER_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define INTEGER_decode_ber ber_decode_primitive
|
||||
der_type_encoder_f INTEGER_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f INTEGER_decode_xer;
|
||||
xer_type_encoder_f INTEGER_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f INTEGER_decode_jer;
|
||||
jer_type_encoder_f INTEGER_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f INTEGER_decode_oer;
|
||||
oer_type_encoder_f INTEGER_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f INTEGER_decode_uper;
|
||||
per_type_encoder_f INTEGER_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f INTEGER_decode_aper;
|
||||
per_type_encoder_f INTEGER_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f INTEGER_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
/***********************************
|
||||
* Some handy conversion routines. *
|
||||
***********************************/
|
||||
|
||||
/*
|
||||
* Natiwe size-independent conversion of native integers to/from INTEGER.
|
||||
* (l_size) is in bytes.
|
||||
* Returns 0 if it was possible to convert, -1 otherwise.
|
||||
* -1/EINVAL: Mandatory argument missing
|
||||
* -1/ERANGE: Value encoded is out of range for long representation
|
||||
* -1/ENOMEM: Memory allocation failed (in asn_*2INTEGER()).
|
||||
*/
|
||||
int asn_INTEGER2imax(const INTEGER_t *i, intmax_t *l);
|
||||
int asn_INTEGER2umax(const INTEGER_t *i, uintmax_t *l);
|
||||
int asn_imax2INTEGER(INTEGER_t *i, intmax_t l);
|
||||
int asn_umax2INTEGER(INTEGER_t *i, uintmax_t l);
|
||||
|
||||
/*
|
||||
* Size-specific conversion helpers.
|
||||
*/
|
||||
int asn_INTEGER2long(const INTEGER_t *i, long *l);
|
||||
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
|
||||
int asn_long2INTEGER(INTEGER_t *i, long l);
|
||||
int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
|
||||
int asn_INTEGER2int64(const INTEGER_t *i, int64_t *l);
|
||||
int asn_INTEGER2uint64(const INTEGER_t *i, uint64_t *l);
|
||||
int asn_int642INTEGER(INTEGER_t *i, int64_t l);
|
||||
int asn_uint642INTEGER(INTEGER_t *i, uint64_t l);
|
||||
|
||||
/* A version of strtol/strtoimax(3) with nicer error reporting. */
|
||||
enum asn_strtox_result_e {
|
||||
ASN_STRTOX_ERROR_RANGE = -3, /* Input outside of supported numeric range */
|
||||
ASN_STRTOX_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
|
||||
ASN_STRTOX_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
|
||||
ASN_STRTOX_OK = 0, /* Conversion succeeded, number ends at (*end) */
|
||||
ASN_STRTOX_EXTRA_DATA = 1 /* Conversion succeeded, but the string has extra stuff */
|
||||
};
|
||||
enum asn_strtox_result_e asn_strtol_lim(const char *str, const char **end,
|
||||
long *l);
|
||||
enum asn_strtox_result_e asn_strtoul_lim(const char *str, const char **end,
|
||||
unsigned long *l);
|
||||
enum asn_strtox_result_e asn_strtoimax_lim(const char *str, const char **end,
|
||||
intmax_t *l);
|
||||
enum asn_strtox_result_e asn_strtoumax_lim(const char *str, const char **end,
|
||||
uintmax_t *l);
|
||||
|
||||
/*
|
||||
* Convert the integer value into the corresponding enumeration map entry.
|
||||
*/
|
||||
const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(
|
||||
const asn_INTEGER_specifics_t *specs, long value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INTEGER_H_ */
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
INTEGER_t *st = (INTEGER_t *)*sptr;
|
||||
const asn_per_constraint_t *ct;
|
||||
asn_per_constraint_t ct_ext_copy; /* Local copy for extension case */
|
||||
int repeat;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(!st) {
|
||||
st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.per_constraints;
|
||||
ct = constraints ? &constraints->value : 0;
|
||||
|
||||
if(ct && ct->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) ASN__DECODE_STARVED;
|
||||
if(inext) {
|
||||
/* In extension: treat as semi-constrained with only lower bound */
|
||||
ct_ext_copy = *ct;
|
||||
ct_ext_copy.flags = APC_SEMI_CONSTRAINED;
|
||||
ct_ext_copy.range_bits = -1;
|
||||
ct_ext_copy.effective_bits = -1;
|
||||
/* Keep lower_bound, discard upper_bound */
|
||||
ct = &ct_ext_copy;
|
||||
}
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = 0;
|
||||
st->size = 0;
|
||||
if(ct) {
|
||||
if(ct->flags & APC_SEMI_CONSTRAINED) {
|
||||
st->buf = (uint8_t *)CALLOC(1, 2);
|
||||
if(!st->buf) ASN__DECODE_FAILED;
|
||||
st->size = 1;
|
||||
} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
|
||||
size_t size = (ct->range_bits + 7) >> 3;
|
||||
st->buf = (uint8_t *)MALLOC(1 + size + 1);
|
||||
if(!st->buf) ASN__DECODE_FAILED;
|
||||
st->size = size;
|
||||
}
|
||||
}
|
||||
|
||||
/* X.691, #12.2.2 */
|
||||
if(ct && ct->flags != APC_UNCONSTRAINED) {
|
||||
/* #10.5.6 */
|
||||
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
|
||||
if(ct->range_bits >= 0) {
|
||||
if (ct->range_bits > 16) {
|
||||
int max_range_bytes = (ct->range_bits >> 3) +
|
||||
(((ct->range_bits % 8) > 0) ? 1 : 0);
|
||||
int length = 0, i;
|
||||
intmax_t value = 0;
|
||||
|
||||
for (i = 1; ; i++) {
|
||||
int upper = 1 << i;
|
||||
if (upper >= max_range_bytes)
|
||||
break;
|
||||
}
|
||||
ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,
|
||||
max_range_bytes, i);
|
||||
|
||||
if ((length = per_get_few_bits(pd, i)) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
|
||||
/* X.691 #12.2.6 length determinant + lb (1) */
|
||||
length += 1;
|
||||
ASN_DEBUG("Got length %d", length);
|
||||
if (aper_get_align(pd) != 0)
|
||||
ASN__DECODE_FAILED;
|
||||
while (length--) {
|
||||
int buf = per_get_few_bits(pd, 8);
|
||||
if (buf < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
value += (((intmax_t)buf) << (8 * length));
|
||||
}
|
||||
|
||||
value += ct->lower_bound;
|
||||
/* Validate the decoded value is within the constraint bounds */
|
||||
if(specs && specs->field_unsigned) {
|
||||
if((uintmax_t)value > (uintmax_t)ct->upper_bound)
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_umax2INTEGER(st, (uintmax_t)value))
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
if(value < ct->lower_bound || value > ct->upper_bound)
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_imax2INTEGER(st, value))
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
ASN_DEBUG("Got value %"ASN_PRIdMAX" + low %"ASN_PRIdMAX"",
|
||||
value, (intmax_t)ct->lower_bound);
|
||||
} else {
|
||||
intmax_t value = 0;
|
||||
if (ct->range_bits < 8) {
|
||||
value = per_get_few_bits(pd, ct->range_bits);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
} else if (ct->range_bits == 8) {
|
||||
if (aper_get_align(pd) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
value = per_get_few_bits(pd, ct->range_bits);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
} else {
|
||||
/* Align */
|
||||
if (aper_get_align(pd) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
value = per_get_few_bits(pd, 16);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
}
|
||||
value += ct->lower_bound;
|
||||
/* Validate the decoded value is within the constraint bounds */
|
||||
if(specs && specs->field_unsigned) {
|
||||
if((uintmax_t)value > (uintmax_t)ct->upper_bound)
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_umax2INTEGER(st, (uintmax_t)value))
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
if(value < ct->lower_bound || value > ct->upper_bound)
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_imax2INTEGER(st, value))
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
ASN_DEBUG("Got value %"ASN_PRIdMAX" + low %"ASN_PRIdMAX"",
|
||||
value, (intmax_t)ct->lower_bound);
|
||||
}
|
||||
return rval;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
} else {
|
||||
ASN_DEBUG("Decoding unconstrained integer %s", td->name);
|
||||
}
|
||||
|
||||
/* X.691, #12.2.3, #12.2.4 */
|
||||
do {
|
||||
ssize_t len;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
/* Get the PER length */
|
||||
len = aper_get_length(pd, -1, -1, -1, &repeat);
|
||||
if(len < 0) ASN__DECODE_STARVED;
|
||||
|
||||
p = REALLOC(st->buf, st->size + len + 1);
|
||||
if(!p) ASN__DECODE_FAILED;
|
||||
st->buf = (uint8_t *)p;
|
||||
|
||||
ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
|
||||
if(ret < 0) ASN__DECODE_STARVED;
|
||||
st->size += len;
|
||||
} while(repeat);
|
||||
st->buf[st->size] = 0; /* JIC */
|
||||
|
||||
/* #12.2.3 */
|
||||
if(ct && ct->lower_bound) {
|
||||
/*
|
||||
* TODO: replace by in-place arithmetics.
|
||||
*/
|
||||
long value;
|
||||
if(asn_INTEGER2long(st, &value))
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_long2INTEGER(st, value + ct->lower_bound))
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
const INTEGER_t *st = (const INTEGER_t *)sptr;
|
||||
const uint8_t *buf;
|
||||
const uint8_t *end;
|
||||
const asn_per_constraint_t *ct;
|
||||
intmax_t value = 0;
|
||||
|
||||
if(!st || st->size == 0) ASN__ENCODE_FAILED;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.per_constraints;
|
||||
ct = constraints ? &constraints->value : 0;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
if(ct) {
|
||||
int inext = 0;
|
||||
if(specs && specs->field_unsigned) {
|
||||
uintmax_t uval;
|
||||
if(asn_INTEGER2umax(st, &uval))
|
||||
ASN__ENCODE_FAILED;
|
||||
/* Check proper range */
|
||||
if(ct->flags & APC_SEMI_CONSTRAINED) {
|
||||
if(uval < (uintmax_t)ct->lower_bound)
|
||||
inext = 1;
|
||||
} else if(ct->range_bits >= 0) {
|
||||
if(uval < (uintmax_t)ct->lower_bound
|
||||
|| uval > (uintmax_t)ct->upper_bound)
|
||||
inext = 1;
|
||||
}
|
||||
ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%"ASN_PRI_SIZE") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
|
||||
uval, st->buf[0], st->size,
|
||||
(intmax_t)ct->lower_bound,
|
||||
(intmax_t)ct->upper_bound,
|
||||
inext ? "ext" : "fix");
|
||||
value = uval;
|
||||
} else {
|
||||
if(asn_INTEGER2imax(st, &value)) ASN__ENCODE_FAILED;
|
||||
/* Check proper range */
|
||||
if(ct->flags & APC_SEMI_CONSTRAINED) {
|
||||
if(value < ct->lower_bound)
|
||||
inext = 1;
|
||||
} else if(ct->range_bits >= 0) {
|
||||
if(value < ct->lower_bound
|
||||
|| value > ct->upper_bound)
|
||||
inext = 1;
|
||||
}
|
||||
ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%"ASN_PRI_SIZE") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
|
||||
value, st->buf[0], st->size,
|
||||
(intmax_t)ct->lower_bound,
|
||||
(intmax_t)ct->upper_bound,
|
||||
inext ? "ext" : "fix");
|
||||
}
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
if(inext) ct = 0;
|
||||
} else if(inext) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* X.691, #12.2.2 */
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
uintmax_t v;
|
||||
|
||||
/* #10.5.6 */
|
||||
ASN_DEBUG("Encoding integer %"ASN_PRIdMAX" (%"ASN_PRIdMAX") with range %d bits",
|
||||
value, (intmax_t)(value - ct->lower_bound),
|
||||
ct->range_bits);
|
||||
|
||||
v = value - ct->lower_bound;
|
||||
|
||||
/* #12 <= 8 -> alignment ? */
|
||||
int range = ct->upper_bound - ct->lower_bound + 1;
|
||||
if (ct->range_bits < 8 || (ct->range_bits == 8 && range < 256)) {
|
||||
if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
|
||||
ASN__ENCODE_FAILED;
|
||||
} else if (ct->range_bits == 8) {
|
||||
if(aper_put_align(po) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
|
||||
ASN__ENCODE_FAILED;
|
||||
} else if (ct->range_bits <= 16) {
|
||||
/* Consume the bytes to align on octet */
|
||||
if(aper_put_align(po) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
if(per_put_few_bits(po, 0x0000 | v, 16))
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
/* TODO: extend to >64 bits */
|
||||
int64_t v64 = v;
|
||||
int i, j;
|
||||
int max_range_bytes = (ct->range_bits >> 3) +
|
||||
(((ct->range_bits % 8) > 0) ? 1 : 0);
|
||||
|
||||
for (i = 1; ; i++) {
|
||||
int upper = 1 << i;
|
||||
if (upper >= max_range_bytes)
|
||||
break;
|
||||
}
|
||||
|
||||
for (j = sizeof(int64_t) -1; j != 0; j--) {
|
||||
int64_t val;
|
||||
val = v64 >> (j * 8);
|
||||
if (val != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Putting length in the minimum number of bits ex: 5 = 3bits */
|
||||
if (per_put_few_bits(po, j, i))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/* Consume the bits to align on octet */
|
||||
if (aper_put_align(po) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
/* Put the value */
|
||||
for (i = 0; i <= j; i++) {
|
||||
if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
if(ct && ct->lower_bound) {
|
||||
ASN_DEBUG("Adjust lower bound to %"ASN_PRIdMAX"", (intmax_t)ct->lower_bound);
|
||||
/* TODO: adjust lower bound */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
for(buf = st->buf, end = st->buf + st->size; buf < end;) {
|
||||
int need_eom = 0;
|
||||
ssize_t mayEncode = aper_put_length(po, -1, -1, end - buf, &need_eom);
|
||||
if(mayEncode < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
if(per_put_many_bits(po, buf, 8 * mayEncode))
|
||||
ASN__ENCODE_FAILED;
|
||||
buf += mayEncode;
|
||||
if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0))
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
/*
|
||||
* Encode INTEGER type using DER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const INTEGER_t *st = (const INTEGER_t *)sptr;
|
||||
asn_enc_rval_t rval;
|
||||
INTEGER_t effective_integer;
|
||||
|
||||
ASN_DEBUG("%s %s as INTEGER (tm=%d)",
|
||||
cb?"Encoding":"Estimating", td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Canonicalize integer in the buffer.
|
||||
* (Remove too long sign extension, remove some first 0x00 bytes)
|
||||
*/
|
||||
if(st->buf) {
|
||||
uint8_t *buf = st->buf;
|
||||
uint8_t *end1 = buf + st->size - 1;
|
||||
int shift;
|
||||
|
||||
/* Compute the number of superfluous leading bytes */
|
||||
for(; buf < end1; buf++) {
|
||||
/*
|
||||
* If the contents octets of an integer value encoding
|
||||
* consist of more than one octet, then the bits of the
|
||||
* first octet and bit 8 of the second octet:
|
||||
* a) shall not all be ones; and
|
||||
* b) shall not all be zero.
|
||||
*/
|
||||
switch(*buf) {
|
||||
case 0x00:
|
||||
if((buf[1] & 0x80) == 0) continue;
|
||||
break;
|
||||
case 0xff:
|
||||
if((buf[1] & 0x80)) continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remove leading superfluous bytes from the integer */
|
||||
shift = buf - st->buf;
|
||||
if(shift) {
|
||||
union {
|
||||
const uint8_t *c_buf;
|
||||
uint8_t *nc_buf;
|
||||
} unconst;
|
||||
unconst.c_buf = st->buf;
|
||||
effective_integer.buf = unconst.nc_buf + shift;
|
||||
effective_integer.size = st->size - shift;
|
||||
|
||||
st = &effective_integer;
|
||||
}
|
||||
}
|
||||
|
||||
rval = der_encode_primitive(td, st, tag_mode, tag, cb, app_key);
|
||||
if(rval.structure_ptr == &effective_integer) {
|
||||
rval.structure_ptr = sptr;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
struct je2v_key {
|
||||
const char *start;
|
||||
const char *stop;
|
||||
const asn_INTEGER_enum_map_t *vemap;
|
||||
const unsigned int *evmap;
|
||||
};
|
||||
|
||||
static int
|
||||
INTEGER_jer_st_prealloc(INTEGER_t *st, int min_size) {
|
||||
void *p = MALLOC(min_size + 1);
|
||||
if(p) {
|
||||
void *b = st->buf;
|
||||
st->size = 0;
|
||||
st->buf = p;
|
||||
FREEMEM(b);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Decode the chunk of JSON text encoding INTEGER.
|
||||
*/
|
||||
static enum jer_pbd_rval
|
||||
INTEGER__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
INTEGER_t *st = (INTEGER_t *)sptr;
|
||||
intmax_t dec_value;
|
||||
const char *lp;
|
||||
const char *lstart = (const char *)chunk_buf;
|
||||
const char *lstop = lstart + chunk_size;
|
||||
enum {
|
||||
ST_LEADSPACE,
|
||||
ST_WAITDIGITS,
|
||||
ST_DIGITS,
|
||||
ST_ZERO,
|
||||
ST_DIGITS_TRAILSPACE,
|
||||
ST_UNEXPECTED
|
||||
} state = ST_LEADSPACE;
|
||||
const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
|
||||
const char *dec_value_end = 0;
|
||||
|
||||
if(chunk_size)
|
||||
ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
|
||||
(long)chunk_size, *lstart, lstop[-1]);
|
||||
|
||||
if(INTEGER_jer_st_prealloc(st, (chunk_size/3) + 1))
|
||||
return JPBD_SYSTEM_FAILURE;
|
||||
|
||||
/*
|
||||
* We may have received a tag here. It will be processed inline.
|
||||
* Use strtoul()-like code and serialize the result.
|
||||
*/
|
||||
for(lp = lstart; lp < lstop; lp++) {
|
||||
int lv = *lp;
|
||||
switch(lv) {
|
||||
case 0x09: case 0x0a: case 0x0d: case 0x20:
|
||||
switch(state) {
|
||||
case ST_LEADSPACE:
|
||||
case ST_DIGITS_TRAILSPACE:
|
||||
continue;
|
||||
case ST_DIGITS:
|
||||
case ST_ZERO:
|
||||
dec_value_end = lp;
|
||||
state = ST_DIGITS_TRAILSPACE;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2d: /* '-' */
|
||||
if(state == ST_LEADSPACE) {
|
||||
dec_value = 0;
|
||||
dec_value_start = lp;
|
||||
state = ST_WAITDIGITS;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x30: /* 0 */
|
||||
switch(state) {
|
||||
case ST_DIGITS: continue;
|
||||
case ST_LEADSPACE:
|
||||
case ST_WAITDIGITS:
|
||||
dec_value = 0;
|
||||
dec_value_start = lp;
|
||||
state = ST_ZERO;
|
||||
continue;
|
||||
case ST_ZERO: /* forbidden leading zero */
|
||||
return JPBD_BROKEN_ENCODING;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* [1-9] */
|
||||
case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
switch(state) {
|
||||
case ST_DIGITS: continue;
|
||||
case ST_LEADSPACE:
|
||||
dec_value = 0;
|
||||
dec_value_start = lp;
|
||||
/* FALL THROUGH */
|
||||
case ST_WAITDIGITS:
|
||||
state = ST_DIGITS;
|
||||
continue;
|
||||
case ST_ZERO: /* forbidden leading zero */
|
||||
return JPBD_BROKEN_ENCODING;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Found extra non-numeric stuff */
|
||||
ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
|
||||
lv, (long)(lp - lstart));
|
||||
state = ST_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(state) {
|
||||
case ST_DIGITS:
|
||||
case ST_ZERO:
|
||||
dec_value_end = lstop;
|
||||
/* FALL THROUGH */
|
||||
case ST_DIGITS_TRAILSPACE:
|
||||
/* The last symbol encountered was a digit. */
|
||||
switch(asn_strtoimax_lim(dec_value_start, &dec_value_end, &dec_value)) {
|
||||
case ASN_STRTOX_OK:
|
||||
if(specs && specs->field_unsigned && (uintmax_t) dec_value <= ULONG_MAX) {
|
||||
break;
|
||||
} else if(dec_value >= LONG_MIN && dec_value <= LONG_MAX) {
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
* We model INTEGER on long for JER,
|
||||
* to avoid rewriting all the tests at once.
|
||||
*/
|
||||
ASN_DEBUG("INTEGER exceeds long range");
|
||||
}
|
||||
/* Fall through */
|
||||
case ASN_STRTOX_ERROR_RANGE:
|
||||
ASN_DEBUG("INTEGER decode %s hit range limit", td->name);
|
||||
return JPBD_DECODER_LIMIT;
|
||||
case ASN_STRTOX_ERROR_INVAL:
|
||||
case ASN_STRTOX_EXPECT_MORE:
|
||||
case ASN_STRTOX_EXTRA_DATA:
|
||||
return JPBD_BROKEN_ENCODING;
|
||||
}
|
||||
break;
|
||||
case ST_LEADSPACE:
|
||||
/* Content not found */
|
||||
return JPBD_NOT_BODY_IGNORE;
|
||||
case ST_WAITDIGITS:
|
||||
case ST_UNEXPECTED:
|
||||
ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
|
||||
return JPBD_BROKEN_ENCODING; /* No digits */
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the result of parsing of enumeration or a straight
|
||||
* decimal value into a BER representation.
|
||||
*/
|
||||
if(asn_imax2INTEGER(st, dec_value)) {
|
||||
ASN_DEBUG("INTEGER decode %s conversion failed", td->name);
|
||||
return JPBD_SYSTEM_FAILURE;
|
||||
}
|
||||
|
||||
return JPBD_BODY_CONSUMED;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
INTEGER_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
void **sptr, const void *buf_ptr, size_t size) {
|
||||
return jer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(INTEGER_t),
|
||||
buf_ptr, size, INTEGER__jer_body_decode);
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel, enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const INTEGER_t *st = (const INTEGER_t *)sptr;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = INTEGER__dump(td, st, cb, app_key, 2);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
INTEGER_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
INTEGER_t *st = (INTEGER_t *)*sptr;
|
||||
struct asn_oer_constraint_number_s ct = {0, 0};
|
||||
size_t req_bytes;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)specs;
|
||||
|
||||
if(!st) {
|
||||
st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = 0;
|
||||
st->size = 0;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints) ct = constraints->value;
|
||||
|
||||
if(ct.width) {
|
||||
req_bytes = ct.width;
|
||||
} else {
|
||||
/* No lower bound and no upper bound, effectively */
|
||||
|
||||
ssize_t consumed = oer_fetch_length(ptr, size, &req_bytes);
|
||||
if(consumed == 0) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else if(consumed == -1) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
rval.consumed += consumed;
|
||||
ptr = (const char *)ptr + consumed;
|
||||
size -= consumed;
|
||||
}
|
||||
|
||||
if(req_bytes == 0 || req_bytes > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
if(ct.positive) {
|
||||
/* X.969 08/2015 10.2(a) */
|
||||
unsigned msb; /* Most significant bit */
|
||||
size_t useful_size;
|
||||
|
||||
/* Check most significant bit */
|
||||
msb = *(const uint8_t *)ptr >> 7; /* yields 0 or 1 */
|
||||
useful_size = msb + req_bytes;
|
||||
st->buf = (uint8_t *)MALLOC(useful_size + 1);
|
||||
if(!st->buf) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record a large unsigned in a way not to confuse it
|
||||
* with signed value.
|
||||
*/
|
||||
st->buf[0] = '\0';
|
||||
memcpy(st->buf + msb, ptr, req_bytes);
|
||||
st->buf[useful_size] = '\0'; /* Just in case, 0-terminate */
|
||||
st->size = useful_size;
|
||||
|
||||
rval.consumed += req_bytes;
|
||||
return rval;
|
||||
} else {
|
||||
/* X.969 08/2015 10.2(b) */
|
||||
st->buf = (uint8_t *)MALLOC(req_bytes + 1);
|
||||
if(!st->buf) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memcpy(st->buf, ptr, req_bytes);
|
||||
st->buf[req_bytes] = '\0'; /* Just in case, 0-terminate */
|
||||
st->size = req_bytes;
|
||||
|
||||
rval.consumed += req_bytes;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, const void *sptr,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const INTEGER_t *st = sptr;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
struct asn_oer_constraint_number_s ct = {0, 0};
|
||||
const uint8_t *buf;
|
||||
const uint8_t *end;
|
||||
size_t useful_bytes;
|
||||
size_t req_bytes = 0;
|
||||
int sign = 0;
|
||||
|
||||
if(!st || st->size == 0) ASN__ENCODE_FAILED;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints) ct = constraints->value;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
|
||||
sign = (buf && buf < end) ? buf[0] & 0x80 : 0;
|
||||
|
||||
/* Ignore 9 leading zeroes or ones */
|
||||
if(ct.positive) {
|
||||
if(sign) {
|
||||
/* The value given is a signed value. Can't proceed. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
/* Remove leading zeros. */
|
||||
for(; buf + 1 < end; buf++) {
|
||||
if(buf[0] != 0x0) break;
|
||||
}
|
||||
} else {
|
||||
for(; buf + 1 < end; buf++) {
|
||||
if(buf[0] == 0x0 && (buf[1] & 0x80) == 0) {
|
||||
continue;
|
||||
} else if(buf[0] == 0xff && (buf[1] & 0x80) != 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
useful_bytes = end - buf;
|
||||
if(ct.width) {
|
||||
req_bytes = ct.width;
|
||||
} else {
|
||||
ssize_t r = oer_serialize_length(useful_bytes, cb, app_key);
|
||||
if(r < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
er.encoded += r;
|
||||
req_bytes = useful_bytes;
|
||||
}
|
||||
|
||||
if(req_bytes < useful_bytes) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
er.encoded += req_bytes;
|
||||
|
||||
for(; req_bytes > useful_bytes; req_bytes--) {
|
||||
if(cb(sign?"\xff":"\0", 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(cb(buf, useful_bytes, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
/*
|
||||
* INTEGER specific human-readable output.
|
||||
*/
|
||||
int
|
||||
INTEGER_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const INTEGER_t *st = (const INTEGER_t *)sptr;
|
||||
ssize_t ret;
|
||||
|
||||
(void)ilevel;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ret = cb("<absent>", 8, app_key);
|
||||
else
|
||||
ret = INTEGER__dump(td, st, cb, app_key, 0);
|
||||
|
||||
return (ret < 0) ? -1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
asn_random_fill_result_t
|
||||
INTEGER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
INTEGER_t *st = *sptr;
|
||||
const asn_INTEGER_enum_map_t *emap;
|
||||
size_t emap_len;
|
||||
intmax_t value;
|
||||
int find_inside_map;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (INTEGER_t *)CALLOC(1, sizeof(*st));
|
||||
if(st == NULL) {
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
if(specs) {
|
||||
emap = specs->value2enum;
|
||||
emap_len = specs->map_count;
|
||||
if(specs->strict_enumeration) {
|
||||
find_inside_map = emap_len > 0;
|
||||
} else {
|
||||
find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
|
||||
}
|
||||
} else {
|
||||
emap = 0;
|
||||
emap_len = 0;
|
||||
find_inside_map = 0;
|
||||
}
|
||||
|
||||
if(find_inside_map) {
|
||||
assert(emap_len > 0);
|
||||
value = emap[asn_random_between(0, emap_len - 1)].nat_value;
|
||||
} else {
|
||||
static const long variants[] = {
|
||||
-65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
|
||||
-16383, -257, -256, -255, -254, -129, -128, -127,
|
||||
-126, -1, 0, 1, 126, 127, 128, 129,
|
||||
254, 255, 256, 257, 16383, 16384, 16385, 32767,
|
||||
32768, 32769, 65534, 65535, 65536, 65537};
|
||||
if(specs && specs->field_unsigned) {
|
||||
assert(variants[18] == 0);
|
||||
value = variants[asn_random_between(
|
||||
18, sizeof(variants) / sizeof(variants[0]) - 1)];
|
||||
} else {
|
||||
value = variants[asn_random_between(
|
||||
0, sizeof(variants) / sizeof(variants[0]) - 1)];
|
||||
}
|
||||
|
||||
if(!constraints) constraints = &td->encoding_constraints;
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
const asn_per_constraints_t *ct;
|
||||
|
||||
ct = constraints ? constraints->per_constraints : 0;
|
||||
if(ct && (ct->value.flags & APC_CONSTRAINED)) {
|
||||
if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
|
||||
value = asn_random_between(ct->value.lower_bound,
|
||||
ct->value.upper_bound);
|
||||
}
|
||||
}
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
}
|
||||
|
||||
if(asn_imax2INTEGER(st, value)) {
|
||||
if(st == *sptr) {
|
||||
ASN_STRUCT_RESET(*td, st);
|
||||
} else {
|
||||
ASN_STRUCT_FREE(*td, st);
|
||||
}
|
||||
return result_failed;
|
||||
} else {
|
||||
*sptr = st;
|
||||
result_ok.length = st->size;
|
||||
return result_ok;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
INTEGER_t *st = (INTEGER_t *)*sptr;
|
||||
const asn_per_constraint_t *ct;
|
||||
int repeat;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(!st) {
|
||||
st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.per_constraints;
|
||||
ct = constraints ? &constraints->value : 0;
|
||||
|
||||
if(ct && ct->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) ASN__DECODE_STARVED;
|
||||
if(inext) ct = 0;
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = 0;
|
||||
st->size = 0;
|
||||
if(ct) {
|
||||
if(ct->flags & APC_SEMI_CONSTRAINED) {
|
||||
st->buf = (uint8_t *)CALLOC(1, 2);
|
||||
if(!st->buf) ASN__DECODE_FAILED;
|
||||
st->size = 1;
|
||||
} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
|
||||
size_t size = (ct->range_bits + 7) >> 3;
|
||||
st->buf = (uint8_t *)MALLOC(1 + size + 1);
|
||||
if(!st->buf) ASN__DECODE_FAILED;
|
||||
st->size = size;
|
||||
}
|
||||
}
|
||||
|
||||
/* X.691-2008/11, #13.2.2, constrained whole number */
|
||||
if(ct && ct->flags != APC_UNCONSTRAINED) {
|
||||
/* #11.5.6 */
|
||||
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
|
||||
if(ct->range_bits >= 0) {
|
||||
if((size_t)ct->range_bits > 8 * sizeof(uintmax_t))
|
||||
ASN__DECODE_FAILED;
|
||||
|
||||
if(specs && specs->field_unsigned) {
|
||||
uintmax_t uvalue = 0;
|
||||
if(uper_get_constrained_whole_number(pd,
|
||||
&uvalue, ct->range_bits))
|
||||
ASN__DECODE_STARVED;
|
||||
ASN_DEBUG("Got value %"ASN_PRIuMAX" + low %"ASN_PRIdMAX"",
|
||||
uvalue, ct->lower_bound);
|
||||
uvalue += ct->lower_bound;
|
||||
if (uvalue > (uintmax_t)ct->upper_bound)
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_umax2INTEGER(st, uvalue))
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
uintmax_t uvalue = 0;
|
||||
intmax_t svalue;
|
||||
if(uper_get_constrained_whole_number(pd,
|
||||
&uvalue, ct->range_bits))
|
||||
ASN__DECODE_STARVED;
|
||||
ASN_DEBUG("Got value %"ASN_PRIuMAX" + low %"ASN_PRIdMAX"",
|
||||
uvalue, ct->lower_bound);
|
||||
if(per_imax_range_unrebase(uvalue, ct->lower_bound,
|
||||
ct->upper_bound, &svalue)
|
||||
|| asn_imax2INTEGER(st, svalue)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
} else {
|
||||
ASN_DEBUG("Decoding unconstrained integer %s", td->name);
|
||||
}
|
||||
|
||||
/* X.691, #12.2.3, #12.2.4 */
|
||||
do {
|
||||
ssize_t len = 0;
|
||||
void *p = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* Get the PER length */
|
||||
len = uper_get_length(pd, -1, 0, &repeat);
|
||||
if(len < 0) ASN__DECODE_STARVED;
|
||||
|
||||
p = REALLOC(st->buf, st->size + len + 1);
|
||||
if(!p) ASN__DECODE_FAILED;
|
||||
st->buf = (uint8_t *)p;
|
||||
|
||||
ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
|
||||
if(ret < 0) ASN__DECODE_STARVED;
|
||||
st->size += len;
|
||||
} while(repeat);
|
||||
st->buf[st->size] = 0; /* JIC */
|
||||
|
||||
/*
|
||||
* Canonical UPER validation: X.691 11.3.6 - minimum octet encoding check.
|
||||
* For unconstrained integers, verify that the encoding uses the minimum
|
||||
* number of octets (leading 8 bits shall not all be zero unless the field
|
||||
* is precisely 8 bits long).
|
||||
*/
|
||||
if(opt_codec_ctx && opt_codec_ctx->uper_canonical && !ct && st->size > 1) {
|
||||
/* Check for non-minimal encoding */
|
||||
if(st->buf[0] == 0x00 && (st->buf[1] & 0x80) == 0) {
|
||||
/* Leading zeros in positive number - not minimal */
|
||||
if(opt_codec_ctx->uper_canonical_lenient) {
|
||||
ASN_DEBUG("Non-canonical UPER: leading zeros in positive integer (lenient mode - continuing)");
|
||||
} else {
|
||||
ASN_DEBUG("Non-canonical UPER: leading zeros in positive integer");
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
} else if(st->buf[0] == 0xFF && (st->buf[1] & 0x80) != 0) {
|
||||
/* Leading ones in negative number - not minimal */
|
||||
if(opt_codec_ctx->uper_canonical_lenient) {
|
||||
ASN_DEBUG("Non-canonical UPER: leading ones in negative integer (lenient mode - continuing)");
|
||||
} else {
|
||||
ASN_DEBUG("Non-canonical UPER: leading ones in negative integer");
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #12.2.3 */
|
||||
if(ct && ct->lower_bound) {
|
||||
/*
|
||||
* TODO: replace by in-place arithmetic.
|
||||
*/
|
||||
long value = 0;
|
||||
if(asn_INTEGER2long(st, &value))
|
||||
ASN__DECODE_FAILED;
|
||||
if(asn_imax2INTEGER(st, value + ct->lower_bound))
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, const void *sptr,
|
||||
asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
const INTEGER_t *st = (const INTEGER_t *)sptr;
|
||||
const uint8_t *buf;
|
||||
const uint8_t *end;
|
||||
const asn_per_constraint_t *ct;
|
||||
union {
|
||||
intmax_t s;
|
||||
uintmax_t u;
|
||||
} value;
|
||||
|
||||
if(!st || st->size == 0) ASN__ENCODE_FAILED;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.per_constraints;
|
||||
ct = constraints ? &constraints->value : 0;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
if(ct) {
|
||||
int inext = 0;
|
||||
if(specs && specs->field_unsigned) {
|
||||
if(asn_INTEGER2umax(st, &value.u))
|
||||
ASN__ENCODE_FAILED;
|
||||
/* Check proper range */
|
||||
if(ct->flags & APC_SEMI_CONSTRAINED) {
|
||||
if(value.u < (uintmax_t)ct->lower_bound)
|
||||
inext = 1;
|
||||
} else if(ct->range_bits >= 0) {
|
||||
if(value.u < (uintmax_t)ct->lower_bound
|
||||
|| value.u > (uintmax_t)ct->upper_bound)
|
||||
inext = 1;
|
||||
}
|
||||
ASN_DEBUG("Value %"ASN_PRIuMAX" (%02x/%" ASN_PRI_SIZE ") lb %"ASN_PRIuMAX" ub %"ASN_PRIuMAX" %s",
|
||||
value.u, st->buf[0], st->size,
|
||||
(uintmax_t)ct->lower_bound, (uintmax_t)ct->upper_bound,
|
||||
inext ? "ext" : "fix");
|
||||
} else {
|
||||
if(asn_INTEGER2imax(st, &value.s))
|
||||
ASN__ENCODE_FAILED;
|
||||
/* Check proper range */
|
||||
if(ct->flags & APC_SEMI_CONSTRAINED) {
|
||||
if(value.s < ct->lower_bound)
|
||||
inext = 1;
|
||||
} else if(ct->range_bits >= 0) {
|
||||
if(value.s < ct->lower_bound
|
||||
|| value.s > ct->upper_bound)
|
||||
inext = 1;
|
||||
}
|
||||
ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%" ASN_PRI_SIZE ") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
|
||||
value.s, st->buf[0], st->size,
|
||||
ct->lower_bound, ct->upper_bound,
|
||||
inext ? "ext" : "fix");
|
||||
}
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
if(inext) ct = 0;
|
||||
} else if(inext) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* X.691-11/2008, #13.2.2, test if constrained whole number */
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
uintmax_t v;
|
||||
/* #11.5.6 -> #11.3 */
|
||||
if(specs && specs->field_unsigned) {
|
||||
if(((uintmax_t)ct->lower_bound > (uintmax_t)(ct->upper_bound)
|
||||
|| (value.u < (uintmax_t)ct->lower_bound))
|
||||
|| (value.u > (uintmax_t)ct->upper_bound)) {
|
||||
ASN_DEBUG("Value %"ASN_PRIuMAX" to-be-encoded is outside the bounds [%"ASN_PRIuMAX", %"ASN_PRIuMAX"]!",
|
||||
value.u, (uintmax_t)ct->lower_bound, (uintmax_t)ct->upper_bound);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
v = value.u - (uintmax_t)ct->lower_bound;
|
||||
} else {
|
||||
if(per_imax_range_rebase(value.s, ct->lower_bound, ct->upper_bound, &v)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
ASN_DEBUG("Encoding integer %"ASN_PRIuMAX" with range %d bits",
|
||||
v, ct->range_bits);
|
||||
if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
|
||||
ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
if(ct && ct->lower_bound) {
|
||||
ASN_DEBUG("Adjust lower bound to %"ASN_PRIdMAX"", ct->lower_bound);
|
||||
/* TODO: adjust lower bound */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
for(buf = st->buf, end = st->buf + st->size; buf < end;) {
|
||||
int need_eom = 0;
|
||||
ssize_t mayEncode = uper_put_length(po, end - buf, &need_eom);
|
||||
if(mayEncode < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
if(per_put_many_bits(po, buf, 8 * mayEncode))
|
||||
ASN__ENCODE_FAILED;
|
||||
buf += mayEncode;
|
||||
if(need_eom && uper_put_length(po, 0, 0)) ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
struct e2v_key {
|
||||
const char *start;
|
||||
const char *stop;
|
||||
const asn_INTEGER_enum_map_t *vemap;
|
||||
const unsigned int *evmap;
|
||||
};
|
||||
static int
|
||||
INTEGER__compar_enum2value(const void *kp, const void *am) {
|
||||
const struct e2v_key *key = (const struct e2v_key *)kp;
|
||||
const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
|
||||
const char *ptr, *end, *name;
|
||||
|
||||
/* Remap the element (sort by different criterion) */
|
||||
el = key->vemap + key->evmap[el - key->vemap];
|
||||
|
||||
/* Compare strings */
|
||||
for(ptr = key->start, end = key->stop, name = el->enum_name;
|
||||
ptr < end; ptr++, name++) {
|
||||
if(*ptr != *name || !*name)
|
||||
return *(const unsigned char *)ptr - *(const unsigned char *)name;
|
||||
}
|
||||
return name[0] ? -1 : 0;
|
||||
}
|
||||
|
||||
static const asn_INTEGER_enum_map_t *
|
||||
INTEGER_map_enum2value(const asn_INTEGER_specifics_t *specs, const char *lstart,
|
||||
const char *lstop) {
|
||||
const asn_INTEGER_enum_map_t *el_found;
|
||||
int count = specs ? specs->map_count : 0;
|
||||
struct e2v_key key;
|
||||
const char *lp;
|
||||
|
||||
if(!count) return NULL;
|
||||
|
||||
/* Guaranteed: assert(lstart < lstop); */
|
||||
/* Figure out the tag name */
|
||||
for(lstart++, lp = lstart; lp < lstop; lp++) {
|
||||
switch(*lp) {
|
||||
case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
|
||||
case 0x2f: /* '/' */ case 0x3e: /* '>' */
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(lp == lstop) return NULL; /* No tag found */
|
||||
lstop = lp;
|
||||
|
||||
key.start = lstart;
|
||||
key.stop = lstop;
|
||||
key.vemap = specs->value2enum;
|
||||
key.evmap = specs->enum2value;
|
||||
el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
|
||||
specs->value2enum, count, sizeof(specs->value2enum[0]),
|
||||
INTEGER__compar_enum2value);
|
||||
if(el_found) {
|
||||
/* Remap enum2value into value2enum */
|
||||
el_found = key.vemap + key.evmap[el_found - key.vemap];
|
||||
}
|
||||
return el_found;
|
||||
}
|
||||
|
||||
static int
|
||||
INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
|
||||
void *p = MALLOC(min_size + 1);
|
||||
if(p) {
|
||||
void *b = st->buf;
|
||||
st->size = 0;
|
||||
st->buf = p;
|
||||
FREEMEM(b);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding INTEGER.
|
||||
*/
|
||||
static enum xer_pbd_rval
|
||||
INTEGER__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
INTEGER_t *st = (INTEGER_t *)sptr;
|
||||
intmax_t dec_value;
|
||||
intmax_t hex_value = 0;
|
||||
const char *lp;
|
||||
const char *lstart = (const char *)chunk_buf;
|
||||
const char *lstop = lstart + chunk_size;
|
||||
enum {
|
||||
ST_LEADSPACE,
|
||||
ST_SKIPSPHEX,
|
||||
ST_WAITDIGITS,
|
||||
ST_DIGITS,
|
||||
ST_DIGITS_TRAILSPACE,
|
||||
ST_HEXDIGIT1,
|
||||
ST_HEXDIGIT2,
|
||||
ST_HEXDIGITS_TRAILSPACE,
|
||||
ST_HEXCOLON,
|
||||
ST_END_ENUM,
|
||||
ST_UNEXPECTED
|
||||
} state = ST_LEADSPACE;
|
||||
const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
|
||||
const char *dec_value_end = 0;
|
||||
|
||||
if(chunk_size)
|
||||
ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
|
||||
(long)chunk_size, *lstart, lstop[-1]);
|
||||
|
||||
if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
|
||||
return XPBD_SYSTEM_FAILURE;
|
||||
|
||||
/*
|
||||
* We may have received a tag here. It will be processed inline.
|
||||
* Use strtoul()-like code and serialize the result.
|
||||
*/
|
||||
for(lp = lstart; lp < lstop; lp++) {
|
||||
int lv = *lp;
|
||||
switch(lv) {
|
||||
case 0x09: case 0x0a: case 0x0d: case 0x20:
|
||||
switch(state) {
|
||||
case ST_LEADSPACE:
|
||||
case ST_DIGITS_TRAILSPACE:
|
||||
case ST_HEXDIGITS_TRAILSPACE:
|
||||
case ST_SKIPSPHEX:
|
||||
continue;
|
||||
case ST_DIGITS:
|
||||
dec_value_end = lp;
|
||||
state = ST_DIGITS_TRAILSPACE;
|
||||
continue;
|
||||
case ST_HEXCOLON:
|
||||
state = ST_HEXDIGITS_TRAILSPACE;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2d: /* '-' */
|
||||
if(state == ST_LEADSPACE) {
|
||||
dec_value = 0;
|
||||
dec_value_start = lp;
|
||||
state = ST_WAITDIGITS;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x2b: /* '+' */
|
||||
if(state == ST_LEADSPACE) {
|
||||
dec_value = 0;
|
||||
dec_value_start = lp;
|
||||
state = ST_WAITDIGITS;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
switch(state) {
|
||||
case ST_DIGITS: continue;
|
||||
case ST_SKIPSPHEX: /* Fall through */
|
||||
case ST_HEXDIGIT1:
|
||||
hex_value = (lv - 0x30) << 4;
|
||||
state = ST_HEXDIGIT2;
|
||||
continue;
|
||||
case ST_HEXDIGIT2:
|
||||
hex_value += (lv - 0x30);
|
||||
state = ST_HEXCOLON;
|
||||
st->buf[st->size++] = (uint8_t)hex_value;
|
||||
continue;
|
||||
case ST_HEXCOLON:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
case ST_LEADSPACE:
|
||||
dec_value = 0;
|
||||
dec_value_start = lp;
|
||||
/* FALL THROUGH */
|
||||
case ST_WAITDIGITS:
|
||||
state = ST_DIGITS;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x3c: /* '<', start of XML encoded enumeration */
|
||||
if(state == ST_LEADSPACE) {
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
el = INTEGER_map_enum2value(
|
||||
(const asn_INTEGER_specifics_t *)
|
||||
td->specifics, lstart, lstop);
|
||||
if(el) {
|
||||
ASN_DEBUG("Found \"%s\" => %ld",
|
||||
el->enum_name, el->nat_value);
|
||||
dec_value = el->nat_value;
|
||||
state = ST_END_ENUM;
|
||||
lp = lstop - 1;
|
||||
continue;
|
||||
}
|
||||
ASN_DEBUG("Unknown identifier for INTEGER");
|
||||
}
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
case 0x3a: /* ':' */
|
||||
if(state == ST_HEXCOLON) {
|
||||
/* This colon is expected */
|
||||
state = ST_HEXDIGIT1;
|
||||
continue;
|
||||
} else if(state == ST_DIGITS) {
|
||||
/* The colon here means that we have
|
||||
* decoded the first two hexadecimal
|
||||
* places as a decimal value.
|
||||
* Switch decoding mode. */
|
||||
ASN_DEBUG("INTEGER re-evaluate as hex form");
|
||||
state = ST_SKIPSPHEX;
|
||||
dec_value_start = 0;
|
||||
lp = lstart - 1;
|
||||
continue;
|
||||
} else {
|
||||
ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
|
||||
break;
|
||||
}
|
||||
/* [A-Fa-f] */
|
||||
case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
|
||||
case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
|
||||
switch(state) {
|
||||
case ST_SKIPSPHEX:
|
||||
case ST_LEADSPACE: /* Fall through */
|
||||
case ST_HEXDIGIT1:
|
||||
hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
|
||||
hex_value += 10;
|
||||
hex_value <<= 4;
|
||||
state = ST_HEXDIGIT2;
|
||||
continue;
|
||||
case ST_HEXDIGIT2:
|
||||
hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
|
||||
hex_value += 10;
|
||||
st->buf[st->size++] = (uint8_t)hex_value;
|
||||
state = ST_HEXCOLON;
|
||||
continue;
|
||||
case ST_DIGITS:
|
||||
ASN_DEBUG("INTEGER re-evaluate as hex form");
|
||||
state = ST_SKIPSPHEX;
|
||||
dec_value_start = 0;
|
||||
lp = lstart - 1;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Found extra non-numeric stuff */
|
||||
ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
|
||||
lv, (long)(lp - lstart));
|
||||
state = ST_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(state) {
|
||||
case ST_END_ENUM:
|
||||
/* Got a complete and valid enumeration encoded as a tag. */
|
||||
break;
|
||||
case ST_DIGITS:
|
||||
dec_value_end = lstop;
|
||||
/* FALL THROUGH */
|
||||
case ST_DIGITS_TRAILSPACE:
|
||||
/* The last symbol encountered was a digit. */
|
||||
switch(asn_strtoimax_lim(dec_value_start, &dec_value_end, &dec_value)) {
|
||||
case ASN_STRTOX_OK:
|
||||
if(specs && specs->field_unsigned && (uintmax_t) dec_value <= ULONG_MAX) {
|
||||
break;
|
||||
} else if(dec_value >= LONG_MIN && dec_value <= LONG_MAX) {
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
* We model INTEGER on long for XER,
|
||||
* to avoid rewriting all the tests at once.
|
||||
*/
|
||||
ASN_DEBUG("INTEGER exceeds long range");
|
||||
}
|
||||
/* Fall through */
|
||||
case ASN_STRTOX_ERROR_RANGE:
|
||||
ASN_DEBUG("INTEGER decode %s hit range limit", td->name);
|
||||
return XPBD_DECODER_LIMIT;
|
||||
case ASN_STRTOX_ERROR_INVAL:
|
||||
case ASN_STRTOX_EXPECT_MORE:
|
||||
case ASN_STRTOX_EXTRA_DATA:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
}
|
||||
break;
|
||||
case ST_HEXCOLON:
|
||||
case ST_HEXDIGITS_TRAILSPACE:
|
||||
st->buf[st->size] = 0; /* Just in case termination */
|
||||
return XPBD_BODY_CONSUMED;
|
||||
case ST_HEXDIGIT1:
|
||||
case ST_HEXDIGIT2:
|
||||
case ST_SKIPSPHEX:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
case ST_LEADSPACE:
|
||||
/* Content not found */
|
||||
return XPBD_NOT_BODY_IGNORE;
|
||||
case ST_WAITDIGITS:
|
||||
case ST_UNEXPECTED:
|
||||
ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
|
||||
return XPBD_BROKEN_ENCODING; /* No digits */
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the result of parsing of enumeration or a straight
|
||||
* decimal value into a BER representation.
|
||||
*/
|
||||
if(asn_imax2INTEGER(st, dec_value)) {
|
||||
ASN_DEBUG("INTEGER decode %s conversion failed", td->name);
|
||||
return XPBD_SYSTEM_FAILURE;
|
||||
}
|
||||
|
||||
return XPBD_BODY_CONSUMED;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
INTEGER_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
return xer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(INTEGER_t), opt_mname,
|
||||
buf_ptr, size, INTEGER__xer_body_decode);
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const INTEGER_t *st = (const INTEGER_t *)sptr;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "ISO646String.h"
|
||||
|
||||
/*
|
||||
* ISO646String basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_ISO646String_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
static asn_per_constraints_t asn_DEF_ISO646String_per_constraints = {
|
||||
{ APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
|
||||
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
|
||||
0, 0
|
||||
};
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
asn_TYPE_operation_t asn_OP_ISO646String = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
OCTET_STRING_print_utf8, /* ASCII subset */
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_utf8,
|
||||
OCTET_STRING_encode_xer_utf8,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_utf8,
|
||||
OCTET_STRING_encode_jer_utf8,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper,
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper,
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
OCTET_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ISO646String = {
|
||||
"ISO646String",
|
||||
"ISO646String",
|
||||
&asn_OP_ISO646String,
|
||||
asn_DEF_ISO646String_tags,
|
||||
sizeof(asn_DEF_ISO646String_tags)
|
||||
/ sizeof(asn_DEF_ISO646String_tags[0]) - 1,
|
||||
asn_DEF_ISO646String_tags,
|
||||
sizeof(asn_DEF_ISO646String_tags)
|
||||
/ sizeof(asn_DEF_ISO646String_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
&asn_DEF_ISO646String_per_constraints,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
ISO646String_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _ISO646String_H_
|
||||
#define _ISO646String_H_
|
||||
|
||||
#include "asn_application.h"
|
||||
#include "VisibleString.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef VisibleString_t ISO646String_t; /* Implemented using VisibleString */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ISO646String;
|
||||
extern asn_TYPE_operation_t asn_OP_ISO646String;
|
||||
|
||||
#define ISO646String_free OCTET_STRING_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define ISO646String_print OCTET_STRING_print_utf8
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define ISO646String_compare OCTET_STRING_compare
|
||||
#define ISO646String_copy OCTET_STRING_copy
|
||||
|
||||
#define ISO646String_constraint VisibleString_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
#define ISO646String_decode_ber OCTET_STRING_decode_ber
|
||||
#define ISO646String_encode_der OCTET_STRING_encode_der
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
#define ISO646String_decode_xer OCTET_STRING_decode_xer_utf8
|
||||
#define ISO646String_encode_xer OCTET_STRING_encode_xer_utf8
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
#define ISO646String_decode_jer OCTET_STRING_decode_jer_utf8
|
||||
#define ISO646String_encode_jer OCTET_STRING_encode_jer_utf8
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
#define ISO646String_decode_oer OCTET_STRING_decode_oer
|
||||
#define ISO646String_encode_oer OCTET_STRING_encode_oer
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
#define ISO646String_decode_uper OCTET_STRING_decode_uper
|
||||
#define ISO646String_encode_uper OCTET_STRING_encode_uper
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
#define ISO646String_decode_aper OCTET_STRING_decode_aper
|
||||
#define ISO646String_encode_aper OCTET_STRING_encode_aper
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
#define ISO646String_random_fill OCTET_STRING_random_fill
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ISO646String_H_ */
|
||||
@@ -0,0 +1,131 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
/*
|
||||
* NULL basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NULL_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (5 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NULL = {
|
||||
NULL_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
NULL_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
NULL_compare,
|
||||
NULL_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
NULL_decode_ber,
|
||||
NULL_encode_der, /* Special handling of DER encoding */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
NULL_decode_xer,
|
||||
NULL_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
NULL_decode_jer,
|
||||
NULL_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
NULL_decode_oer,
|
||||
NULL_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
NULL_decode_uper, /* Unaligned PER decoder */
|
||||
NULL_encode_uper, /* Unaligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
NULL_decode_aper, /* Aligned PER decoder */
|
||||
NULL_encode_aper, /* Aligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
NULL_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NULL = {
|
||||
"NULL",
|
||||
"NULL",
|
||||
&asn_OP_NULL,
|
||||
asn_DEF_NULL_tags,
|
||||
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
|
||||
asn_DEF_NULL_tags, /* Same as above */
|
||||
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
void
|
||||
NULL_free(const asn_TYPE_descriptor_t *td, void *ptr,
|
||||
enum asn_struct_free_method method) {
|
||||
if(td && ptr) {
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(ptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET:
|
||||
memset(ptr, 0, sizeof(NULL_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NULL_compare(const asn_TYPE_descriptor_t *td, const void *a, const void *b) {
|
||||
(void)td;
|
||||
(void)a;
|
||||
(void)b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NULL_copy(const asn_TYPE_descriptor_t *td, void **a, const void *b) {
|
||||
(void)td;
|
||||
|
||||
if(b && !*a) {
|
||||
*a = CALLOC(1, sizeof(NULL_t));
|
||||
if (!*a) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_TYPE_NULL_H
|
||||
#define ASN_TYPE_NULL_H
|
||||
|
||||
#include "asn_application.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The value of the NULL type is meaningless.
|
||||
* Use the BOOLEAN type if you need to carry true/false semantics.
|
||||
*/
|
||||
typedef int NULL_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NULL;
|
||||
extern asn_TYPE_operation_t asn_OP_NULL;
|
||||
|
||||
asn_struct_free_f NULL_free;
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f NULL_print;
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f NULL_compare;
|
||||
asn_struct_copy_f NULL_copy;
|
||||
|
||||
#define NULL_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_type_decoder_f NULL_decode_ber;
|
||||
der_type_encoder_f NULL_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f NULL_decode_xer;
|
||||
xer_type_encoder_f NULL_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f NULL_decode_jer;
|
||||
jer_type_encoder_f NULL_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f NULL_decode_oer;
|
||||
oer_type_encoder_f NULL_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f NULL_decode_uper;
|
||||
per_type_encoder_f NULL_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f NULL_decode_aper;
|
||||
per_type_encoder_f NULL_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f NULL_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NULL_H */
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rv = {RC_OK, 0};
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)pd;
|
||||
|
||||
if(!*sptr) {
|
||||
*sptr = MALLOC(sizeof(NULL_t));
|
||||
if(*sptr) {
|
||||
*(NULL_t *)*sptr = 0;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NULL type does not have content octets but has to align
|
||||
*/
|
||||
|
||||
if (aper_get_align(pd) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)sptr;
|
||||
(void)po;
|
||||
|
||||
if (aper_put_align(po) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = 0;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
/*
|
||||
* Decode NULL type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NULL_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **bool_value,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
NULL_t *st = (NULL_t *)*bool_value;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (NULL_t *)(*bool_value = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as NULL (tm=%d)", td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
|
||||
&length, 0);
|
||||
if(rval.code != RC_OK) {
|
||||
return rval;
|
||||
}
|
||||
|
||||
// X.690-201508, #8.8.2, length shall be zero.
|
||||
if(length != 0) {
|
||||
ASN_DEBUG("Decoding %s as NULL failed: too much data", td->name);
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_der(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode,
|
||||
ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
|
||||
erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key);
|
||||
if(erval.encoded == -1) {
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = ptr;
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(erval);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "asn_codecs_prim.h"
|
||||
#include "NULL.h"
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints, const void *sptr,
|
||||
int ilevel, enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
ASN__CALLBACK("null", 4);
|
||||
ASN__ENCODED_OK(er);
|
||||
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
|
||||
static enum jer_pbd_rval
|
||||
NULL__jer_body_decode(const asn_TYPE_descriptor_t *td,
|
||||
void *sptr, const void *chunk_buf, size_t chunk_size) {
|
||||
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
|
||||
const char *p = (const char *)chunk_buf;
|
||||
|
||||
if(chunk_size && p[0] == 'n' /* 'null' */) {
|
||||
return JPBD_BODY_CONSUMED;
|
||||
} else {
|
||||
return JPBD_BROKEN_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
void **sptr, const void *buf_ptr, size_t size) {
|
||||
return jer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(NULL_t), buf_ptr, size,
|
||||
NULL__jer_body_decode);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
asn_dec_rval_t rv = {RC_OK, 0};
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
|
||||
if(!*sptr) {
|
||||
*sptr = MALLOC(sizeof(NULL_t));
|
||||
if(*sptr) {
|
||||
*(NULL_t *)*sptr = 0;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, const void *sptr,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)constraints;
|
||||
(void)cb;
|
||||
(void)app_key;
|
||||
|
||||
er.encoded = 0; /* Encoding in 0 bytes. */
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
int
|
||||
NULL_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(sptr) {
|
||||
return (cb("<present>", 9, app_key) < 0) ? -1 : 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
asn_random_fill_result_t
|
||||
NULL_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constr,
|
||||
size_t max_length) {
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
NULL_t *st = *sptr;
|
||||
|
||||
(void)td;
|
||||
(void)constr;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (NULL_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return result_ok;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NULL.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rv;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)pd;
|
||||
|
||||
if(!*sptr) {
|
||||
*sptr = MALLOC(sizeof(NULL_t));
|
||||
if(*sptr) {
|
||||
*(NULL_t *)*sptr = 0;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NULL type does not have content octets.
|
||||
*/
|
||||
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, const void *sptr,
|
||||
asn_per_outp_t *po) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)sptr;
|
||||
(void)po;
|
||||
|
||||
er.encoded = 0;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "asn_codecs_prim.h"
|
||||
#include "NULL.h"
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
(void)cb;
|
||||
(void)app_key;
|
||||
|
||||
/* XMLNullValue is empty */
|
||||
er.encoded = 0;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
|
||||
static enum xer_pbd_rval
|
||||
NULL__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)chunk_buf; /* Going to be empty according to the rules below. */
|
||||
|
||||
/*
|
||||
* There must be no content in self-terminating <NULL/> tag.
|
||||
*/
|
||||
if(chunk_size)
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
else
|
||||
return XPBD_BODY_CONSUMED;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
return xer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(NULL_t), opt_mname, buf_ptr, size,
|
||||
NULL__xer_body_decode);
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*-
|
||||
* Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Read the NativeInteger.h for the explanation wrt. differences between
|
||||
* 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.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
/*
|
||||
* NativeEnumerated basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NativeEnumerated = {
|
||||
NativeInteger_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
NativeInteger_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
NativeInteger_compare,
|
||||
NativeInteger_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
NativeEnumerated_decode_ber,
|
||||
NativeEnumerated_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
NativeEnumerated_decode_xer,
|
||||
NativeEnumerated_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
NativeEnumerated_decode_jer,
|
||||
NativeEnumerated_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
NativeEnumerated_decode_oer,
|
||||
NativeEnumerated_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
NativeEnumerated_decode_uper,
|
||||
NativeEnumerated_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
NativeEnumerated_decode_aper,
|
||||
NativeEnumerated_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
NativeEnumerated_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
|
||||
int
|
||||
NativeEnumerated_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
const long *native = (const long *)sptr;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
el = INTEGER_map_value2enum(specs, *native);
|
||||
if(el) {
|
||||
return 0;
|
||||
} else {
|
||||
ASN_DEBUG("No element corresponds to the value %ld", *native);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
|
||||
"ENUMERATED", /* The ASN.1 type is still ENUMERATED */
|
||||
"ENUMERATED",
|
||||
&asn_OP_NativeEnumerated,
|
||||
asn_DEF_NativeEnumerated_tags,
|
||||
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
|
||||
asn_DEF_NativeEnumerated_tags, /* Same as above */
|
||||
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
NativeEnumerated_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
int
|
||||
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
|
||||
const asn_INTEGER_enum_map_t *a = ap;
|
||||
const asn_INTEGER_enum_map_t *b = bp;
|
||||
if(a->nat_value == b->nat_value)
|
||||
return 0;
|
||||
if(a->nat_value < b->nat_value)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* This type differs from the standard ENUMERATED in that it is modelled using
|
||||
* the fixed machine type (long, int, short), so it can hold only values of
|
||||
* limited length. There is no type (i.e., NativeEnumerated_t, any integer type
|
||||
* will do).
|
||||
* This type may be used when integer range is limited by subtype constraints.
|
||||
*/
|
||||
#ifndef _NativeEnumerated_H_
|
||||
#define _NativeEnumerated_H_
|
||||
|
||||
#include "NativeInteger.h"
|
||||
#include "ENUMERATED.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
|
||||
extern asn_TYPE_operation_t asn_OP_NativeEnumerated;
|
||||
|
||||
#define NativeEnumerated_free NativeInteger_free
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
#define NativeEnumerated_print NativeInteger_print
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
#define NativeEnumerated_compare NativeInteger_compare
|
||||
#define NativeEnumerated_copy NativeInteger_copy
|
||||
|
||||
asn_constr_check_f NativeEnumerated_constraint;
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_type_decoder_f NativeEnumerated_decode_ber;
|
||||
der_type_encoder_f NativeEnumerated_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f NativeEnumerated_decode_xer;
|
||||
xer_type_encoder_f NativeEnumerated_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f NativeEnumerated_decode_jer;
|
||||
jer_type_encoder_f NativeEnumerated_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f NativeEnumerated_decode_oer;
|
||||
oer_type_encoder_f NativeEnumerated_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f NativeEnumerated_decode_uper;
|
||||
per_type_encoder_f NativeEnumerated_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f NativeEnumerated_decode_aper;
|
||||
per_type_encoder_f NativeEnumerated_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
#define NativeEnumerated_random_fill NativeInteger_random_fill
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
int NativeEnumerated__compar_value2enum(
|
||||
const void *ap,
|
||||
const void *bp);
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NativeEnumerated_H_ */
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
void **sptr, asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
long *native = (long *)*sptr;
|
||||
const asn_per_constraint_t *ct;
|
||||
long value;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(constraints) ct = &constraints->value;
|
||||
else if(td->encoding_constraints.per_constraints)
|
||||
ct = &td->encoding_constraints.per_constraints->value;
|
||||
else ASN__DECODE_FAILED; /* Mandatory! */
|
||||
if(!specs) ASN__DECODE_FAILED;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
|
||||
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) ASN__DECODE_STARVED;
|
||||
if(inext) ct = 0;
|
||||
}
|
||||
|
||||
/* Deal with APER padding */
|
||||
if(ct && ct->upper_bound >= 255) {
|
||||
int padding = 0;
|
||||
padding = (8 - (pd->moved % 8)) % 8;
|
||||
ASN_DEBUG("For NativeEnumerated %s,offset = %zu Padding bits = %d",
|
||||
td->name, pd->moved, padding);
|
||||
ASN_DEBUG("For NativeEnumerated %s, upper bound = %llu",
|
||||
td->name, (unsigned long long)ct->upper_bound);
|
||||
if(padding > 0)
|
||||
per_get_few_bits(pd, padding);
|
||||
}
|
||||
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
value = per_get_few_bits(pd, ct->range_bits);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
if(value >= (specs->extension
|
||||
? specs->extension - 1 : specs->map_count))
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
if(!specs->extension)
|
||||
ASN__DECODE_FAILED;
|
||||
/*
|
||||
* X.691, #10.6: normally small non-negative whole number;
|
||||
*/
|
||||
|
||||
/* XXX handle indefinite index length > 64k */
|
||||
value = aper_get_nsnnwn(pd);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
value += specs->extension - 1;
|
||||
//if(value >= specs->map_count)
|
||||
// ASN__DECODE_FAILED;
|
||||
if(value >= specs->map_count) {
|
||||
ASN_DEBUG("Decoded unknown index value %s = %ld", td->name, value);
|
||||
/* unknown index. Workaround => set the first enumeration value */
|
||||
*native = specs->value2enum[0].nat_value;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
*native = specs->value2enum[value].nat_value;
|
||||
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
long native, value;
|
||||
const asn_per_constraint_t *ct;
|
||||
int inext = 0, range_bits = 1;
|
||||
asn_INTEGER_enum_map_t key;
|
||||
asn_INTEGER_enum_map_t *kf;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
if(!specs) ASN__ENCODE_FAILED;
|
||||
|
||||
if(constraints) ct = &constraints->value;
|
||||
else if(td->encoding_constraints.per_constraints)
|
||||
ct = &td->encoding_constraints.per_constraints->value;
|
||||
else ASN__ENCODE_FAILED; /* Mandatory! */
|
||||
|
||||
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
if(native < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
key.nat_value = native;
|
||||
kf = bsearch(&key, specs->value2enum, specs->map_count,
|
||||
sizeof(key), NativeEnumerated__compar_value2enum);
|
||||
if(!kf) {
|
||||
ASN_DEBUG("No element corresponds to %ld", native);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
value = kf - specs->value2enum;
|
||||
|
||||
if(ct->range_bits >= 0) {
|
||||
int cmpWith = specs->extension
|
||||
? specs->extension - 1 : specs->map_count;
|
||||
if(value >= cmpWith)
|
||||
inext = 1;
|
||||
}
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
if(inext) range_bits = 0;
|
||||
} else if(inext) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(range_bits && ct && ct->range_bits >= 0) {
|
||||
if(per_put_few_bits(po, value, ct->range_bits))
|
||||
ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
if(!specs->extension)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/*
|
||||
* X.691, #10.6: normally small non-negative whole number;
|
||||
*/
|
||||
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
|
||||
value, specs->extension, inext,
|
||||
value - (inext ? (specs->extension - 1) : 0));
|
||||
if(aper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "INTEGER.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
/*
|
||||
* Decode NativeEnumerated type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **nint_ptr,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
long *native = (long *)*nint_ptr;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
|
||||
/*
|
||||
* If the structure is not there, allocate it.
|
||||
*/
|
||||
if(native == NULL) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(native == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as NativeEnumerated (tm=%d)",
|
||||
td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
|
||||
tag_mode, 0, &length, 0);
|
||||
if(rval.code != RC_OK)
|
||||
return rval;
|
||||
|
||||
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
|
||||
|
||||
/*
|
||||
* Make sure we have this length.
|
||||
*/
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ASN.1 encoded NativeEnumerated: buf_ptr, length
|
||||
* Fill the native, at the same time checking for overflow.
|
||||
* If overflow occurred, return with RC_FAIL.
|
||||
*/
|
||||
{
|
||||
INTEGER_t tmp;
|
||||
union {
|
||||
const void *constbuf;
|
||||
void *nonconstbuf;
|
||||
} unconst_buf;
|
||||
long l;
|
||||
|
||||
unconst_buf.constbuf = buf_ptr;
|
||||
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
|
||||
tmp.size = length;
|
||||
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&tmp, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
el = INTEGER_map_value2enum(specs, l);
|
||||
if(!el) {
|
||||
ASN_DEBUG("No element corresponds to the value %ld", l);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = el->nat_value;
|
||||
}
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
|
||||
(long)rval.consumed, (long)length, td->name, (long)*native);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode the NativeEnumerated using the standard INTEGER type DER encoder.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
unsigned long native = *(const unsigned long *)sptr; /* Disable sign ext. */
|
||||
|
||||
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
INTEGER_t tmp;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
|
||||
el = INTEGER_map_value2enum(specs, native);
|
||||
if(!el) {
|
||||
ASN_DEBUG(
|
||||
"No elemenet corresponds to the value %ld", native);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
|
||||
|
||||
tmp.buf = (uint8_t *)&native;
|
||||
tmp.size = sizeof(native);
|
||||
|
||||
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
|
||||
uint8_t buf[sizeof(native)];
|
||||
uint8_t *p;
|
||||
|
||||
/* Prepare a fake INTEGER */
|
||||
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
|
||||
*p = (uint8_t)native;
|
||||
|
||||
tmp.buf = buf;
|
||||
tmp.size = sizeof(buf);
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
/* Encode fake INTEGER */
|
||||
erval = INTEGER_encode_der(td, &tmp, tag_mode, tag, cb, app_key);
|
||||
if(erval.structure_ptr == &tmp) {
|
||||
erval.structure_ptr = sptr;
|
||||
}
|
||||
return erval;
|
||||
}
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
/*
|
||||
* Decode the chunk of JSON text encoding ENUMERATED.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints, void **sptr,
|
||||
const void *buf_ptr, size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
INTEGER_t st;
|
||||
void *st_ptr = (void *)&st;
|
||||
long *native = (long *)*sptr;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
rval = ENUMERATED_decode_jer(opt_codec_ctx, td, constraints, &st_ptr, buf_ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
long l;
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&st, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
} else {
|
||||
*native = l;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Cannot restart from the middle;
|
||||
* there is no place to save state in the native type.
|
||||
* Request a continuation from the very beginning.
|
||||
*/
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel, enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
const long *native = (const long *)sptr;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!native) ASN__ENCODE_FAILED;
|
||||
|
||||
el = INTEGER_map_value2enum(specs, *native);
|
||||
if(el) {
|
||||
er.encoded =
|
||||
asn__format_to_callback(cb, app_key, "\"%s\"", el->enum_name);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
} else {
|
||||
ASN_DEBUG(
|
||||
"ASN.1 forbids dealing with "
|
||||
"unknown value of ENUMERATED type");
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
static long
|
||||
asn__nativeenumerated_convert(const uint8_t *b, const uint8_t *end) {
|
||||
unsigned long value;
|
||||
|
||||
/* Perform the sign initialization */
|
||||
/* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
|
||||
if((*b >> 7)) {
|
||||
value = (unsigned long)(-1);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
/* Conversion engine */
|
||||
for(; b < end; b++) {
|
||||
value = (value << 8) | *b;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
void **nint_ptr, const void *ptr, size_t size) {
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
long *native = (long *)*nint_ptr;
|
||||
const uint8_t *b = ptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
|
||||
if(size < 1) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
if((*b & 0x80) == 0) {
|
||||
/*
|
||||
* X.696 (08/2015) #11.2 Short form for Enumerated.
|
||||
*/
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = *b;
|
||||
rval.consumed = 1;
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #11.4 Long form for Enumerated.
|
||||
*/
|
||||
size_t length = *b & 0x7f;
|
||||
const uint8_t *bend;
|
||||
long value;
|
||||
|
||||
if(length < 1 || length > sizeof(*native)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
if((1 + length) > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
b++;
|
||||
bend = b + length;
|
||||
|
||||
value = asn__nativeenumerated_convert(b, bend);
|
||||
if(value < 0) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
if(specs && specs->field_unsigned) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = value;
|
||||
|
||||
rval.consumed = (1 + length);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
long native;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
if(native >= 0 && native <= 127) {
|
||||
/* #11.2 Short form */
|
||||
uint8_t b = native;
|
||||
er.encoded = 1;
|
||||
if(cb(&b, er.encoded, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
} else {
|
||||
/* #11.2 Long form */
|
||||
uint8_t buf[1 + sizeof(native)];
|
||||
uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
|
||||
long final_pattern = -1 * (native < 0);
|
||||
|
||||
for(;;) {
|
||||
*b-- = native;
|
||||
native >>= 8;
|
||||
if(native == final_pattern) {
|
||||
if(final_pattern) {
|
||||
if((b[1] & 0x80)) break;
|
||||
} else {
|
||||
if(!(b[1] & 0x80)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*b = 0x80 | (&buf[sizeof(native)] - b);
|
||||
er.encoded = 1 + (&buf[sizeof(native)] - b);
|
||||
if(cb(b, er.encoded, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
void **sptr, asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs = td->specifics;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
long *native = (long *)*sptr;
|
||||
const asn_per_constraint_t *ct;
|
||||
long value;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(constraints) ct = &constraints->value;
|
||||
else if(td->encoding_constraints.per_constraints)
|
||||
ct = &td->encoding_constraints.per_constraints->value;
|
||||
else ASN__DECODE_FAILED; /* Mandatory! */
|
||||
if(!specs) ASN__DECODE_FAILED;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
|
||||
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) ASN__DECODE_STARVED;
|
||||
if(inext) ct = 0;
|
||||
}
|
||||
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
value = per_get_few_bits(pd, ct->range_bits);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
if(value >= (specs->extension
|
||||
? specs->extension - 1 : specs->map_count))
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
if(!specs->extension)
|
||||
ASN__DECODE_FAILED;
|
||||
/*
|
||||
* X.691, #10.6: normally small non-negative whole number;
|
||||
*/
|
||||
value = uper_get_nsnnwn(pd);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
value += specs->extension - 1;
|
||||
if(value >= specs->map_count)
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = specs->value2enum[value].nat_value;
|
||||
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
long native, value;
|
||||
const asn_per_constraint_t *ct;
|
||||
int inext = 0;
|
||||
asn_INTEGER_enum_map_t key;
|
||||
const asn_INTEGER_enum_map_t *kf;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
if(!specs) ASN__ENCODE_FAILED;
|
||||
|
||||
if(constraints) ct = &constraints->value;
|
||||
else if(td->encoding_constraints.per_constraints)
|
||||
ct = &td->encoding_constraints.per_constraints->value;
|
||||
else ASN__ENCODE_FAILED; /* Mandatory! */
|
||||
|
||||
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
key.nat_value = native;
|
||||
kf = bsearch(&key, specs->value2enum, specs->map_count,
|
||||
sizeof(key), NativeEnumerated__compar_value2enum);
|
||||
if(!kf) {
|
||||
ASN_DEBUG("No element corresponds to %ld", native);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
value = kf - specs->value2enum;
|
||||
|
||||
if(ct->range_bits >= 0) {
|
||||
int cmpWith = specs->extension
|
||||
? specs->extension - 1 : specs->map_count;
|
||||
if(value >= cmpWith)
|
||||
inext = 1;
|
||||
}
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
if(inext) ct = 0;
|
||||
} else if(inext) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
if(per_put_few_bits(po, value, ct->range_bits))
|
||||
ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
if(!specs->extension)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/*
|
||||
* X.691, #10.6: normally small non-negative whole number;
|
||||
*/
|
||||
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
|
||||
value, specs->extension, inext,
|
||||
value - (inext ? (specs->extension - 1) : 0));
|
||||
if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeEnumerated.h"
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
const long *native = (const long *)sptr;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!native) ASN__ENCODE_FAILED;
|
||||
|
||||
el = INTEGER_map_value2enum(specs, *native);
|
||||
if(el) {
|
||||
er.encoded =
|
||||
asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
} else {
|
||||
ASN_DEBUG("No element corresponds to the value %ld", *native);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr,
|
||||
size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
INTEGER_t st;
|
||||
void *st_ptr = (void *)&st;
|
||||
long *native = (long *)*sptr;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, opt_mname, buf_ptr,
|
||||
size);
|
||||
if(rval.code == RC_OK) {
|
||||
long l;
|
||||
if((specs && specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&st, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
} else {
|
||||
el = INTEGER_map_value2enum(specs, l);
|
||||
if(!el) {
|
||||
ASN_DEBUG("No element corresponds to the value %ld", l);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
*native = el->nat_value;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Cannot restart from the middle;
|
||||
* there is no place to save state in the native type.
|
||||
* Request a continuation from the very beginning.
|
||||
*/
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Read the NativeInteger.h for the explanation wrt. differences between
|
||||
* 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.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
/*
|
||||
* NativeInteger basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NativeInteger = {
|
||||
NativeInteger_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
NativeInteger_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
NativeInteger_compare,
|
||||
NativeInteger_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
NativeInteger_decode_ber,
|
||||
NativeInteger_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
NativeInteger_decode_xer,
|
||||
NativeInteger_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
NativeInteger_decode_jer,
|
||||
NativeInteger_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
NativeInteger_decode_oer, /* OER decoder */
|
||||
NativeInteger_encode_oer, /* Canonical OER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
NativeInteger_decode_uper, /* Unaligned PER decoder */
|
||||
NativeInteger_encode_uper, /* Unaligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
NativeInteger_decode_aper, /* Aligned PER decoder */
|
||||
NativeInteger_encode_aper, /* Aligned PER encoder */
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
NativeInteger_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
|
||||
"INTEGER", /* The ASN.1 type is still INTEGER */
|
||||
"INTEGER",
|
||||
&asn_OP_NativeInteger,
|
||||
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]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
void
|
||||
NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr,
|
||||
enum asn_struct_free_method method) {
|
||||
if(!td || !ptr)
|
||||
return;
|
||||
|
||||
ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
|
||||
td->name, method, ptr);
|
||||
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(ptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET:
|
||||
memset(ptr, 0, sizeof(long));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) {
|
||||
(void)td;
|
||||
|
||||
if(aptr && bptr) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
if(specs && specs->field_unsigned) {
|
||||
const unsigned long *a = aptr;
|
||||
const unsigned long *b = bptr;
|
||||
if(*a < *b) {
|
||||
return -1;
|
||||
} else if(*a > *b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
const long *a = aptr;
|
||||
const long *b = bptr;
|
||||
if(*a < *b) {
|
||||
return -1;
|
||||
} else if(*a > *b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if(!aptr) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NativeInteger_copy(const asn_TYPE_descriptor_t *td, void **aptr, const void *bptr) {
|
||||
unsigned long *a = *aptr;
|
||||
const unsigned long *b = bptr;
|
||||
|
||||
(void)td;
|
||||
|
||||
/* Check if source has data */
|
||||
if(!b) {
|
||||
/* Clear destination */
|
||||
if(a) {
|
||||
FREEMEM(a);
|
||||
*aptr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!a) {
|
||||
a = *aptr = MALLOC(sizeof(*a));
|
||||
if(!a) return -1;
|
||||
}
|
||||
|
||||
*a = *b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* This type differs from the standard INTEGER in that it is modelled using
|
||||
* the fixed machine type (long, int, short), so it can hold only values of
|
||||
* limited length. There is no type (i.e., NativeInteger_t, any integer type
|
||||
* will do).
|
||||
* This type may be used when integer range is limited by subtype constraints.
|
||||
*/
|
||||
#ifndef _NativeInteger_H_
|
||||
#define _NativeInteger_H_
|
||||
|
||||
#include "asn_application.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
|
||||
extern asn_TYPE_operation_t asn_OP_NativeInteger;
|
||||
|
||||
asn_struct_free_f NativeInteger_free;
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f NativeInteger_print;
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f NativeInteger_compare;
|
||||
asn_struct_copy_f NativeInteger_copy;
|
||||
|
||||
#define NativeInteger_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_type_decoder_f NativeInteger_decode_ber;
|
||||
der_type_encoder_f NativeInteger_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f NativeInteger_decode_xer;
|
||||
xer_type_encoder_f NativeInteger_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f NativeInteger_decode_jer;
|
||||
jer_type_encoder_f NativeInteger_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f NativeInteger_decode_oer;
|
||||
oer_type_encoder_f NativeInteger_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f NativeInteger_decode_uper;
|
||||
per_type_encoder_f NativeInteger_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f NativeInteger_decode_aper;
|
||||
per_type_encoder_f NativeInteger_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f NativeInteger_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NativeInteger_H_ */
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
|
||||
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
long *native = (long *)*sptr;
|
||||
INTEGER_t tmpint;
|
||||
void *tmpintptr = &tmpint;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name);
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&tmpint, 0, sizeof tmpint);
|
||||
rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints,
|
||||
&tmpintptr, pd);
|
||||
if(rval.code == RC_OK) {
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
|
||||
: asn_INTEGER2long(&tmpint, native))
|
||||
rval.code = RC_FAIL;
|
||||
else
|
||||
ASN_DEBUG("NativeInteger %s got value %ld",
|
||||
td->name, *native);
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
|
||||
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
long native;
|
||||
INTEGER_t tmpint;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
ASN_DEBUG("Encoding NativeInteger %s %ld (APER)", td->name, native);
|
||||
|
||||
memset(&tmpint, 0, sizeof(tmpint));
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_ulong2INTEGER(&tmpint, (unsigned long)native)
|
||||
: asn_long2INTEGER(&tmpint, native))
|
||||
ASN__ENCODE_FAILED;
|
||||
er = INTEGER_encode_aper(td, constraints, &tmpint, po);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return er;
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
#include "INTEGER.h"
|
||||
|
||||
/*
|
||||
* Decode INTEGER type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **nint_ptr,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
long *native = (long *)*nint_ptr;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
|
||||
/*
|
||||
* If the structure is not there, allocate it.
|
||||
*/
|
||||
if(native == NULL) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(native == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
|
||||
td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
|
||||
tag_mode, 0, &length, 0);
|
||||
if(rval.code != RC_OK)
|
||||
return rval;
|
||||
|
||||
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
|
||||
|
||||
/*
|
||||
* Make sure we have this length.
|
||||
*/
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ASN.1 encoded INTEGER: buf_ptr, length
|
||||
* Fill the native, at the same time checking for overflow.
|
||||
* If overflow occurred, return with RC_FAIL.
|
||||
*/
|
||||
{
|
||||
INTEGER_t tmp;
|
||||
union {
|
||||
const void *constbuf;
|
||||
void *nonconstbuf;
|
||||
} unconst_buf;
|
||||
long l;
|
||||
|
||||
unconst_buf.constbuf = buf_ptr;
|
||||
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
|
||||
tmp.size = length;
|
||||
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&tmp, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
*native = l;
|
||||
}
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
|
||||
(long)rval.consumed, (long)length, td->name, (long)*native);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode the NativeInteger using the standard INTEGER type DER encoder.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_der(const asn_TYPE_descriptor_t *sd, const void *ptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
unsigned long native = *(const unsigned long *)ptr; /* Disable sign ext. */
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
INTEGER_t tmp;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
|
||||
|
||||
tmp.buf = (uint8_t *)&native;
|
||||
tmp.size = sizeof(native);
|
||||
|
||||
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
|
||||
uint8_t buf[sizeof(native)];
|
||||
uint8_t *p;
|
||||
|
||||
/* Prepare a fake INTEGER */
|
||||
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
|
||||
*p = (uint8_t)native;
|
||||
|
||||
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.structure_ptr == &tmp) {
|
||||
erval.structure_ptr = ptr;
|
||||
}
|
||||
return erval;
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
/*
|
||||
* Decode the chunk of JSON text encoding INTEGER.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t* constraints,
|
||||
void **sptr, const void *buf_ptr,
|
||||
size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
INTEGER_t st;
|
||||
void *st_ptr = (void *)&st;
|
||||
long *native = (long *)*sptr;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
rval = INTEGER_decode_jer(opt_codec_ctx, td, constraints, &st_ptr, buf_ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
long l;
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&st, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
} else {
|
||||
*native = l;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Cannot restart from the middle;
|
||||
* there is no place to save state in the native type.
|
||||
* Request a continuation from the very beginning.
|
||||
*/
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t* constraints,
|
||||
const void *sptr, int ilevel,
|
||||
enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
char scratch[32]; /* Enough for 64-bit int */
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
const long *native = (const long *)sptr;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!native) ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = snprintf(scratch, sizeof(scratch),
|
||||
(specs && specs->field_unsigned)
|
||||
? "%lu" : "%ld", *native);
|
||||
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|
||||
|| cb(scratch, er.encoded, app_key) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
void **nint_ptr, const void *ptr, size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
long *native = (long *)*nint_ptr;
|
||||
INTEGER_t tmpint;
|
||||
INTEGER_t *tmpintptr = &tmpint;
|
||||
|
||||
memset(&tmpint, 0, sizeof(tmpint));
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* OPTIMIZATION: Encode directly rather than passing through INTEGER.
|
||||
* Saves a memory allocation.
|
||||
*/
|
||||
rval = INTEGER_decode_oer(opt_codec_ctx, td, constraints,
|
||||
(void **)&tmpintptr, ptr, size);
|
||||
if(rval.code != RC_OK) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return rval;
|
||||
}
|
||||
|
||||
if(specs && specs->field_unsigned) {
|
||||
unsigned long ul;
|
||||
int ok = asn_INTEGER2ulong(&tmpint, &ul) == 0;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
if(ok) {
|
||||
*native = ul;
|
||||
} else {
|
||||
rval.code = RC_FAIL;
|
||||
return rval;
|
||||
}
|
||||
} else {
|
||||
long l;
|
||||
int ok = asn_INTEGER2long(&tmpint, &l) == 0;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
if(ok) {
|
||||
*native = l;
|
||||
} else {
|
||||
rval.code = RC_FAIL;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
INTEGER_t tmpint;
|
||||
long native;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
memset(&tmpint, 0, sizeof(tmpint));
|
||||
|
||||
ASN_DEBUG("Encoding %s %ld as NativeInteger", td ? td->name : "", native);
|
||||
|
||||
if((specs && specs->field_unsigned) ? asn_ulong2INTEGER(&tmpint, native)
|
||||
: asn_long2INTEGER(&tmpint, native)) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
asn_enc_rval_t er =
|
||||
INTEGER_encode_oer(td, constraints, &tmpint, cb, app_key);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return er;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
/*
|
||||
* INTEGER specific human-readable output.
|
||||
*/
|
||||
int
|
||||
NativeInteger_print(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
const long *native = (const long *)sptr;
|
||||
char scratch[32]; /* Enough for 64-bit int */
|
||||
int ret;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(native) {
|
||||
long value = *native;
|
||||
ret = snprintf(scratch, sizeof(scratch),
|
||||
(specs && specs->field_unsigned) ? "%lu" : "%ld", value);
|
||||
assert(ret > 0 && (size_t)ret < sizeof(scratch));
|
||||
if(cb(scratch, ret, app_key) < 0) return -1;
|
||||
if(specs && (value >= 0 || !specs->field_unsigned)) {
|
||||
const asn_INTEGER_enum_map_t *el =
|
||||
INTEGER_map_value2enum(specs, value);
|
||||
if(el) {
|
||||
if(cb(" (", 2, app_key) < 0) return -1;
|
||||
if(cb(el->enum_name, el->enum_len, app_key) < 0) return -1;
|
||||
if(cb(")", 1, app_key) < 0) return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
asn_random_fill_result_t
|
||||
NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
long *st = *sptr;
|
||||
const asn_INTEGER_enum_map_t *emap;
|
||||
size_t emap_len;
|
||||
intmax_t value;
|
||||
int find_inside_map;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (long *)CALLOC(1, sizeof(*st));
|
||||
if(st == NULL) {
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
if(specs) {
|
||||
emap = specs->value2enum;
|
||||
emap_len = specs->map_count;
|
||||
if(specs->strict_enumeration) {
|
||||
find_inside_map = emap_len > 0;
|
||||
} else {
|
||||
find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
|
||||
}
|
||||
} else {
|
||||
emap = 0;
|
||||
emap_len = 0;
|
||||
find_inside_map = 0;
|
||||
}
|
||||
|
||||
if(find_inside_map) {
|
||||
assert(emap_len > 0);
|
||||
value = emap[asn_random_between(0, emap_len - 1)].nat_value;
|
||||
} else {
|
||||
static const long variants[] = {
|
||||
-65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
|
||||
-16383, -257, -256, -255, -254, -129, -128, -127,
|
||||
-126, -1, 0, 1, 126, 127, 128, 129,
|
||||
254, 255, 256, 257, 16383, 16384, 16385, 32767,
|
||||
32768, 32769, 65534, 65535, 65536, 65537};
|
||||
if(specs && specs->field_unsigned) {
|
||||
assert(variants[18] == 0);
|
||||
value = variants[asn_random_between(
|
||||
18, sizeof(variants) / sizeof(variants[0]) - 1)];
|
||||
} else {
|
||||
value = variants[asn_random_between(
|
||||
0, sizeof(variants) / sizeof(variants[0]) - 1)];
|
||||
}
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
if(!constraints || !constraints->per_constraints)
|
||||
constraints = &td->encoding_constraints;
|
||||
|
||||
const asn_per_constraints_t *ct;
|
||||
|
||||
ct = constraints ? constraints->per_constraints : 0;
|
||||
if(ct && (ct->value.flags & APC_CONSTRAINED)) {
|
||||
if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
|
||||
value = asn_random_between(ct->value.lower_bound,
|
||||
ct->value.upper_bound);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(!constraints) constraints = &td->encoding_constraints;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
}
|
||||
|
||||
*sptr = st;
|
||||
*st = value;
|
||||
return result_ok;
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
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)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&tmpint, 0, sizeof tmpint);
|
||||
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
|
||||
&tmpintptr, pd);
|
||||
if(rval.code == RC_OK) {
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
|
||||
: asn_INTEGER2long(&tmpint, native))
|
||||
rval.code = RC_FAIL;
|
||||
else
|
||||
ASN_DEBUG("NativeInteger %s got value %ld",
|
||||
td->name, *native);
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
long native;
|
||||
INTEGER_t tmpint;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const 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))
|
||||
ASN__ENCODE_FAILED;
|
||||
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return er;
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeInteger.h"
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding INTEGER.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr,
|
||||
size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
INTEGER_t st;
|
||||
void *st_ptr = (void *)&st;
|
||||
long *native = (long *)*sptr;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,
|
||||
opt_mname, buf_ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
long l;
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&st, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
} else {
|
||||
*native = l;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Cannot restart from the middle;
|
||||
* there is no place to save state in the native type.
|
||||
* Request a continuation from the very beginning.
|
||||
*/
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
char scratch[32]; /* Enough for 64-bit int */
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
const long *native = (const long *)sptr;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!native) ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = snprintf(scratch, sizeof(scratch),
|
||||
(specs && specs->field_unsigned)
|
||||
? "%lu" : "%ld", *native);
|
||||
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|
||||
|| cb(scratch, er.encoded, app_key) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Read the NativeReal.h for the explanation wrt. differences between
|
||||
* REAL and NativeReal.
|
||||
* Basically, both are decoders and encoders of ASN.1 REAL type, but this
|
||||
* implementation deals with the standard (machine-specific) representation
|
||||
* of them instead of using the platform-independent buffer.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
/*
|
||||
* isnan() is defined using generic selections and won't compile in
|
||||
* strict C89 mode because of too fancy system's standard library.
|
||||
* However, prior to C11 the math had a perfectly working isnan()
|
||||
* in the math library.
|
||||
* Disable generic selection warning so we can test C89 mode with newer libc.
|
||||
*/
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wc11-extensions"
|
||||
static int asn_isnan(double d) {
|
||||
return isnan(d);
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
#else
|
||||
#define asn_isnan(v) isnan(v)
|
||||
#endif /* generic selections */
|
||||
|
||||
/*
|
||||
* NativeReal basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NativeReal = {
|
||||
NativeReal_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
NativeReal_print,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
NativeReal_compare,
|
||||
NativeReal_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
NativeReal_decode_ber,
|
||||
NativeReal_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
NativeReal_decode_xer,
|
||||
NativeReal_encode_xer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
NativeReal_decode_jer,
|
||||
NativeReal_encode_jer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
NativeReal_decode_oer,
|
||||
NativeReal_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
NativeReal_decode_uper,
|
||||
NativeReal_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
NativeReal_decode_aper,
|
||||
NativeReal_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
NativeReal_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NativeReal = {
|
||||
"REAL", /* The ASN.1 type is still REAL */
|
||||
"REAL",
|
||||
&asn_OP_NativeReal,
|
||||
asn_DEF_NativeReal_tags,
|
||||
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
|
||||
asn_DEF_NativeReal_tags, /* Same as above */
|
||||
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
asn_generic_no_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
int
|
||||
NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
|
||||
const void *bptr) {
|
||||
|
||||
if(aptr && bptr) {
|
||||
double a = NativeReal__get_double(td, aptr);
|
||||
double b = NativeReal__get_double(td, bptr);
|
||||
|
||||
/* NaN sorted above everything else */
|
||||
if(asn_isnan(a)) {
|
||||
if(asn_isnan(b)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if(asn_isnan(b)) {
|
||||
return 1;
|
||||
}
|
||||
/* Value comparison. */
|
||||
if(a < b) {
|
||||
return -1;
|
||||
} else if(a > b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if(!aptr) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NativeReal_copy(const asn_TYPE_descriptor_t *td, void **aptr,
|
||||
const void *bptr) {
|
||||
size_t float_size = NativeReal__float_size(td);
|
||||
void *a = *aptr;
|
||||
const void *b = bptr;
|
||||
|
||||
if(!b) {
|
||||
if(a) {
|
||||
FREEMEM(a);
|
||||
*aptr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!a) {
|
||||
a = *aptr = MALLOC(float_size);
|
||||
if(!a) return -1;
|
||||
}
|
||||
|
||||
if(float_size == sizeof(float)) {
|
||||
*(float *)a = *(const float *)b;
|
||||
} else {
|
||||
*(double *)a = *(const double *)b;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr,
|
||||
enum asn_struct_free_method method) {
|
||||
if(!td || !ptr)
|
||||
return;
|
||||
|
||||
ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
|
||||
td->name, method, ptr);
|
||||
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(ptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET: {
|
||||
const asn_NativeReal_specifics_t *specs;
|
||||
size_t float_size;
|
||||
specs = (const asn_NativeReal_specifics_t *)td->specifics;
|
||||
float_size = specs ? specs->float_size : sizeof(double);
|
||||
memset(ptr, 0, float_size);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local helper functions.
|
||||
*/
|
||||
|
||||
size_t
|
||||
NativeReal__float_size(const asn_TYPE_descriptor_t *td) {
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
return specs ? specs->float_size : sizeof(double);
|
||||
}
|
||||
|
||||
double
|
||||
NativeReal__get_double(const asn_TYPE_descriptor_t *td, const void *ptr) {
|
||||
size_t float_size = NativeReal__float_size(td);
|
||||
if(float_size == sizeof(float)) {
|
||||
return *(const float *)ptr;
|
||||
} else {
|
||||
return *(const double *)ptr;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t /* Returns -1 or float size. */
|
||||
NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr, double d) {
|
||||
size_t float_size = NativeReal__float_size(td);
|
||||
void *native;
|
||||
|
||||
if(!(native = *sptr)) {
|
||||
native = (*sptr = CALLOC(1, float_size));
|
||||
if(!native) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(float_size == sizeof(float)) {
|
||||
if(asn_double2float(d, (float *)native)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
*(double *)native = d;
|
||||
}
|
||||
|
||||
return float_size;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* This type differs from the standard REAL in that it is modelled using
|
||||
* the fixed machine type (double), so it can hold only values of
|
||||
* limited precision. There is no explicit type (i.e., NativeReal_t).
|
||||
* Use of this type is normally enabled by -fnative-types.
|
||||
*/
|
||||
#ifndef ASN_TYPE_NativeReal_H
|
||||
#define ASN_TYPE_NativeReal_H
|
||||
|
||||
#include "asn_application.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct asn_NativeReal_specifics_s {
|
||||
unsigned float_size; /* sizeof(float) or sizeof(double) */
|
||||
} asn_NativeReal_specifics_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NativeReal;
|
||||
extern asn_TYPE_operation_t asn_OP_NativeReal;
|
||||
|
||||
size_t NativeReal__float_size(const asn_TYPE_descriptor_t *td);
|
||||
double NativeReal__get_double(const asn_TYPE_descriptor_t *td,
|
||||
const void *ptr);
|
||||
ssize_t NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
double d);
|
||||
|
||||
asn_struct_free_f NativeReal_free;
|
||||
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
asn_struct_print_f NativeReal_print;
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
|
||||
asn_struct_compare_f NativeReal_compare;
|
||||
asn_struct_copy_f NativeReal_copy;
|
||||
|
||||
#define NativeReal_constraint asn_generic_no_constraint
|
||||
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
ber_type_decoder_f NativeReal_decode_ber;
|
||||
der_type_encoder_f NativeReal_encode_der;
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
xer_type_decoder_f NativeReal_decode_xer;
|
||||
xer_type_encoder_f NativeReal_encode_xer;
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
jer_type_decoder_f NativeReal_decode_jer;
|
||||
jer_type_encoder_f NativeReal_encode_jer;
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
oer_type_decoder_f NativeReal_decode_oer;
|
||||
oer_type_encoder_f NativeReal_encode_oer;
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
per_type_decoder_f NativeReal_decode_uper;
|
||||
per_type_encoder_f NativeReal_encode_uper;
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
per_type_decoder_f NativeReal_decode_aper;
|
||||
per_type_encoder_f NativeReal_encode_aper;
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
asn_random_fill_f NativeReal_random_fill;
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_TYPE_NativeReal_H */
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeReal_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
void **dbl_ptr, asn_per_data_t *pd) {
|
||||
double *Dbl = (double *)*dbl_ptr;
|
||||
asn_dec_rval_t rval;
|
||||
REAL_t tmp;
|
||||
void *ptmp = &tmp;
|
||||
int ret;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
/*
|
||||
* If the structure is not there, allocate it.
|
||||
*/
|
||||
if(Dbl == NULL) {
|
||||
*dbl_ptr = CALLOC(1, sizeof(*Dbl));
|
||||
Dbl = (double *)*dbl_ptr;
|
||||
if(Dbl == NULL)
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
rval = OCTET_STRING_decode_aper(opt_codec_ctx, td, NULL,
|
||||
&ptmp, pd);
|
||||
if(rval.code != RC_OK) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
return rval;
|
||||
}
|
||||
|
||||
ret = asn_REAL2double(&tmp, Dbl);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
if(ret) ASN__DECODE_FAILED;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeReal_encode_aper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
double Dbl = *(const double *)sptr;
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
REAL_t tmp;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
/* Prepare a temporary clean structure */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(asn_double2REAL(&tmp, Dbl))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/* Encode a DER REAL */
|
||||
erval = OCTET_STRING_encode_aper(td, NULL, &tmp, po);
|
||||
if(erval.encoded == -1)
|
||||
erval.structure_ptr = sptr;
|
||||
|
||||
/* Free possibly allocated members of the temporary structure */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
|
||||
return erval;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
|
||||
/*
|
||||
* Decode REAL type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeReal_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
|
||||
ASN_DEBUG("Decoding %s as REAL (tm=%d)", td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
|
||||
&length, 0);
|
||||
if(rval.code != RC_OK) return rval;
|
||||
assert(length >= 0); /* Ensured by ber_check_tags */
|
||||
|
||||
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
|
||||
|
||||
/*
|
||||
* Make sure we have this length.
|
||||
*/
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ASN.1 encoded REAL: buf_ptr, length
|
||||
* Fill the Dbl, at the same time checking for overflow.
|
||||
* If overflow occurred, return with RC_FAIL.
|
||||
*/
|
||||
{
|
||||
uint8_t scratch[24]; /* Longer than %.16f in decimal */
|
||||
REAL_t tmp;
|
||||
double d;
|
||||
int ret;
|
||||
|
||||
if((size_t)length < sizeof(scratch)) {
|
||||
tmp.buf = scratch;
|
||||
tmp.size = length;
|
||||
} else {
|
||||
/* This rarely happens: impractically long value */
|
||||
tmp.buf = CALLOC(1, length + 1);
|
||||
tmp.size = length;
|
||||
if(!tmp.buf) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(tmp.buf, buf_ptr, length);
|
||||
tmp.buf[length] = '\0';
|
||||
|
||||
ret = asn_REAL2double(&tmp, &d);
|
||||
if(tmp.buf != scratch) FREEMEM(tmp.buf);
|
||||
if(ret) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
if(NativeReal__set(td, sptr, d) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s", (long)rval.consumed,
|
||||
(long)length, td->name);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode the NativeReal using the standard REAL type DER encoder.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeReal_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
REAL_t tmp;
|
||||
|
||||
/* Prepare a temporary clean structure */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(asn_double2REAL(&tmp, d))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/* Encode a fake REAL */
|
||||
erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
|
||||
if(erval.encoded == -1) {
|
||||
assert(erval.structure_ptr == &tmp);
|
||||
erval.structure_ptr = sptr;
|
||||
}
|
||||
|
||||
/* Free possibly allocated members of the temporary structure */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
|
||||
return erval;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
|
||||
/*
|
||||
* Decode the chunk of JSON text encoding REAL.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeReal_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
void **sptr, const void *buf_ptr, size_t size) {
|
||||
asn_dec_rval_t rval;
|
||||
REAL_t st = { 0, 0 };
|
||||
REAL_t *stp = &st;
|
||||
|
||||
rval = REAL_decode_jer(opt_codec_ctx, td, constraints, (void **)&stp, buf_ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
double d;
|
||||
if(asn_REAL2double(&st, &d) || NativeReal__set(td, sptr, d) < 0) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
}
|
||||
} else {
|
||||
/* Convert all errors into RC_FAIL */
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeReal_encode_jer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_jer_constraints_t *constraints,
|
||||
const void *sptr, int ilevel,
|
||||
enum jer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
double native;
|
||||
REAL_t tmpreal;
|
||||
|
||||
(void)ilevel;
|
||||
|
||||
native = NativeReal__get_double(td, sptr);
|
||||
memset(&tmpreal, 0, sizeof(tmpreal));
|
||||
if(asn_double2REAL(&tmpreal, native))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er = REAL_encode_jer(td, constraints, &tmpreal, ilevel, flags, cb, app_key);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmpreal);
|
||||
return er;
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
|
||||
/*
|
||||
* Swap bytes from/to network, if local is little-endian.
|
||||
* Unused endianness sections are likely removed at compile phase.
|
||||
*/
|
||||
static void
|
||||
NativeReal__network_swap(size_t float_size, const void *srcp, uint8_t *dst) {
|
||||
const uint8_t *src = srcp;
|
||||
double test = -0.0;
|
||||
int float_big_endian = *(const char *)&test != 0;
|
||||
/* In lieu of static_assert(sizeof(double) == 8) */
|
||||
static const char sizeof_double_is_8_a[sizeof(double)-7] CC_NOTUSED;
|
||||
static const char sizeof_double_is_8_b[9-sizeof(double)] CC_NOTUSED;
|
||||
/* In lieu of static_assert(sizeof(sizeof) == 4) */
|
||||
static const char sizeof_float_is_4_a[sizeof(float)-3] CC_NOTUSED;
|
||||
static const char sizeof_float_is_4_b[5-sizeof(float)] CC_NOTUSED;
|
||||
|
||||
switch(float_size) {
|
||||
case sizeof(double):
|
||||
assert(sizeof(double) == 8);
|
||||
if(float_big_endian) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
dst[4] = src[4];
|
||||
dst[5] = src[5];
|
||||
dst[6] = src[6];
|
||||
dst[7] = src[7];
|
||||
} else {
|
||||
dst[0] = src[7];
|
||||
dst[1] = src[6];
|
||||
dst[2] = src[5];
|
||||
dst[3] = src[4];
|
||||
dst[4] = src[3];
|
||||
dst[5] = src[2];
|
||||
dst[6] = src[1];
|
||||
dst[7] = src[0];
|
||||
}
|
||||
return;
|
||||
case sizeof(float):
|
||||
assert(sizeof(float) == 4);
|
||||
if(float_big_endian) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
} else {
|
||||
dst[0] = src[3];
|
||||
dst[1] = src[2];
|
||||
dst[2] = src[1];
|
||||
dst[3] = src[0];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeReal_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints && constraints->value.width != 0) {
|
||||
/* X.696 IEEE 754 binary32 and binary64 encoding */
|
||||
uint8_t scratch[sizeof(double)];
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
size_t wire_size = constraints->value.width;
|
||||
|
||||
if(specs ? (wire_size == specs->float_size)
|
||||
: (wire_size == sizeof(double))) {
|
||||
/*
|
||||
* Our representation matches the wire, modulo endianness.
|
||||
* That was the whole point of compact encoding!
|
||||
*/
|
||||
} else {
|
||||
assert((wire_size == sizeof(double))
|
||||
|| (specs && specs->float_size == wire_size));
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* The X.696 standard doesn't specify endianness, neither is IEEE 754.
|
||||
* So we assume the network format is big endian.
|
||||
*/
|
||||
NativeReal__network_swap(wire_size, sptr, scratch);
|
||||
if(cb(scratch, wire_size, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
er.encoded = wire_size;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
} else {
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
ssize_t len_len;
|
||||
REAL_t tmp;
|
||||
|
||||
/* Prepare a temporary clean structure */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(asn_double2REAL(&tmp, d)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/* Encode a fake REAL */
|
||||
len_len = oer_serialize_length(tmp.size, cb, app_key);
|
||||
if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
er.encoded = len_len + tmp.size;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeReal_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
asn_dec_rval_t ok = {RC_OK, 0};
|
||||
double d;
|
||||
ssize_t len_len;
|
||||
size_t real_body_len;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints && constraints->value.width != 0) {
|
||||
/* X.696 IEEE 754 binary32 and binary64 encoding */
|
||||
uint8_t scratch[sizeof(double)];
|
||||
size_t wire_size = constraints->value.width;
|
||||
|
||||
if(size < wire_size)
|
||||
ASN__DECODE_STARVED;
|
||||
|
||||
/*
|
||||
* The X.696 standard doesn't specify endianness, neither is IEEE 754.
|
||||
* So we assume the network format is big endian.
|
||||
*/
|
||||
NativeReal__network_swap(wire_size, ptr, scratch);
|
||||
|
||||
|
||||
switch(wire_size) {
|
||||
case sizeof(double):
|
||||
{
|
||||
double tmp;
|
||||
memcpy(&tmp, scratch, sizeof(double));
|
||||
if(NativeReal__set(td, sptr, tmp) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
break;
|
||||
case sizeof(float):
|
||||
{
|
||||
float tmp;
|
||||
memcpy(&tmp, scratch, sizeof(float));
|
||||
if(NativeReal__set(td, sptr, tmp) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
ok.consumed = wire_size;
|
||||
return ok;
|
||||
}
|
||||
|
||||
len_len = oer_fetch_length(ptr, size, &real_body_len);
|
||||
if(len_len < 0) ASN__DECODE_FAILED;
|
||||
if(len_len == 0) ASN__DECODE_STARVED;
|
||||
|
||||
ptr = (const char *)ptr + len_len;
|
||||
size -= len_len;
|
||||
|
||||
if(real_body_len > size) ASN__DECODE_STARVED;
|
||||
|
||||
{
|
||||
uint8_t scratch[24]; /* Longer than %.16f in decimal */
|
||||
REAL_t tmp;
|
||||
int ret;
|
||||
|
||||
if(real_body_len < sizeof(scratch)) {
|
||||
tmp.buf = scratch;
|
||||
tmp.size = real_body_len;
|
||||
} else {
|
||||
/* This rarely happens: impractically long value */
|
||||
tmp.buf = CALLOC(1, real_body_len + 1);
|
||||
tmp.size = real_body_len;
|
||||
if(!tmp.buf) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(tmp.buf, ptr, real_body_len);
|
||||
tmp.buf[real_body_len] = '\0';
|
||||
|
||||
ret = asn_REAL2double(&tmp, &d);
|
||||
if(tmp.buf != scratch) FREEMEM(tmp.buf);
|
||||
if(ret) {
|
||||
ASN_DEBUG("REAL decoded in %" ASN_PRI_SIZE " bytes, but can't convert t double",
|
||||
real_body_len);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(NativeReal__set(td, sptr, d) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
|
||||
ok.consumed = len_len + real_body_len;
|
||||
return ok;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
|
||||
/*
|
||||
* REAL specific human-readable output.
|
||||
*/
|
||||
int
|
||||
NativeReal_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(sptr) {
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
return (REAL__dump(d, 0, cb, app_key) < 0) ? -1 : 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
asn_random_fill_result_t
|
||||
NativeReal_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 0};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
#ifndef INFINITY
|
||||
#define INFINITY (1.0/0.0)
|
||||
#endif
|
||||
#ifndef NAN
|
||||
#define NAN (0.0/0.0)
|
||||
#endif
|
||||
static const double double_values[] = {
|
||||
-M_E, M_E, -M_PI, M_PI, /* Better precision than with floats */
|
||||
-1E+308, 1E+308,
|
||||
/* 2^51 */
|
||||
-2251799813685248.0, 2251799813685248.0,
|
||||
/* 2^52 */
|
||||
-4503599627370496.0, 4503599627370496.0,
|
||||
/* 2^100 */
|
||||
-1267650600228229401496703205376.0, 1267650600228229401496703205376.0,
|
||||
-DBL_MIN, DBL_MIN,
|
||||
-DBL_MAX, DBL_MAX,
|
||||
#ifdef DBL_TRUE_MIN
|
||||
-DBL_TRUE_MIN, DBL_TRUE_MIN
|
||||
#endif
|
||||
};
|
||||
static const float float_values[] = {
|
||||
0, -0.0, -1, 1, -M_E, M_E, -3.14, 3.14, -M_PI, M_PI, -255, 255,
|
||||
-FLT_MIN, FLT_MIN,
|
||||
-FLT_MAX, FLT_MAX,
|
||||
#ifdef FLT_TRUE_MIN
|
||||
-FLT_TRUE_MIN, FLT_TRUE_MIN,
|
||||
#endif
|
||||
INFINITY, -INFINITY, NAN
|
||||
};
|
||||
ssize_t float_set_size = NativeReal__float_size(td);
|
||||
const size_t n_doubles = sizeof(double_values) / sizeof(double_values[0]);
|
||||
const size_t n_floats = sizeof(float_values) / sizeof(float_values[0]);
|
||||
double d;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(float_set_size == sizeof(double) && asn_random_between(0, 1) == 0) {
|
||||
d = double_values[asn_random_between(0, n_doubles - 1)];
|
||||
} else {
|
||||
d = float_values[asn_random_between(0, n_floats - 1)];
|
||||
}
|
||||
|
||||
if(NativeReal__set(td, sptr, d) < 0) {
|
||||
return result_failed;
|
||||
}
|
||||
|
||||
result_ok.length = float_set_size;
|
||||
return result_ok;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
#include "OCTET_STRING.h"
|
||||
|
||||
/*
|
||||
* Decode REAL type using PER.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeReal_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rval;
|
||||
double d;
|
||||
REAL_t tmp;
|
||||
void *ptmp = &tmp;
|
||||
int ret;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
rval = OCTET_STRING_decode_uper(opt_codec_ctx, &asn_DEF_REAL,
|
||||
NULL, &ptmp, pd);
|
||||
if(rval.code != RC_OK) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
return rval;
|
||||
}
|
||||
|
||||
ret = asn_REAL2double(&tmp, &d);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
if(ret) ASN__DECODE_FAILED;
|
||||
|
||||
if(NativeReal__set(td, sptr, d) < 0 )
|
||||
ASN__DECODE_FAILED;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode the NativeReal using the OCTET STRING PER encoder.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeReal_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
asn_enc_rval_t erval = {0,0,0};
|
||||
REAL_t tmp;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
/* Prepare a temporary clean structure */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(asn_double2REAL(&tmp, d))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/* Encode a DER REAL */
|
||||
erval = OCTET_STRING_encode_uper(&asn_DEF_REAL, NULL, &tmp, po);
|
||||
if(erval.encoded == -1)
|
||||
erval.structure_ptr = sptr;
|
||||
|
||||
/* Free possibly allocated members of the temporary structure */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
|
||||
return erval;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NativeReal.h"
|
||||
#include "REAL.h"
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding REAL.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeReal_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
asn_dec_rval_t rval;
|
||||
REAL_t st = { 0, 0 };
|
||||
REAL_t *stp = &st;
|
||||
|
||||
rval = REAL_decode_xer(opt_codec_ctx, td, (void **)&stp, opt_mname,
|
||||
buf_ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
double d;
|
||||
if(asn_REAL2double(&st, &d) || NativeReal__set(td, sptr, d) < 0) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
}
|
||||
} else {
|
||||
/* Convert all errors into RC_FAIL */
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeReal_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
asn_enc_rval_t er = {0,0,0};
|
||||
|
||||
(void)ilevel;
|
||||
|
||||
er.encoded = REAL__dump(d, flags & XER_F_CANONICAL, cb, app_key);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include "asn_internal.h"
|
||||
#include "NumericString.h"
|
||||
|
||||
/*
|
||||
* NumericString basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NumericString_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (18 << 2)), /* [UNIVERSAL 18] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
static int asn_DEF_NumericString_v2c(unsigned int value) {
|
||||
switch(value) {
|
||||
case 0x20: return 0;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
return value - (0x30 - 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static int asn_DEF_NumericString_c2v(unsigned int code) {
|
||||
if(code > 0) {
|
||||
if(code <= 10)
|
||||
return code + (0x30 - 1);
|
||||
else
|
||||
return -1;
|
||||
} else {
|
||||
return 0x20;
|
||||
}
|
||||
}
|
||||
static asn_per_constraints_t asn_DEF_NumericString_per_constraints = {
|
||||
{ APC_CONSTRAINED, 4, 4, 0x20, 0x39 }, /* Value */
|
||||
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
|
||||
asn_DEF_NumericString_v2c,
|
||||
asn_DEF_NumericString_c2v
|
||||
};
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
asn_TYPE_operation_t asn_OP_NumericString = {
|
||||
OCTET_STRING_free,
|
||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
|
||||
OCTET_STRING_print_utf8, /* ASCII subset */
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
|
||||
OCTET_STRING_compare,
|
||||
OCTET_STRING_copy,
|
||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
|
||||
OCTET_STRING_decode_xer_utf8,
|
||||
OCTET_STRING_encode_xer_utf8,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
OCTET_STRING_decode_jer_utf8,
|
||||
OCTET_STRING_encode_jer_utf8,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
OCTET_STRING_decode_oer,
|
||||
OCTET_STRING_encode_oer,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
|
||||
OCTET_STRING_decode_uper,
|
||||
OCTET_STRING_encode_uper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
OCTET_STRING_decode_aper,
|
||||
OCTET_STRING_encode_aper,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
|
||||
OCTET_STRING_random_fill,
|
||||
#else
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NumericString = {
|
||||
"NumericString",
|
||||
"NumericString",
|
||||
&asn_OP_NumericString,
|
||||
asn_DEF_NumericString_tags,
|
||||
sizeof(asn_DEF_NumericString_tags)
|
||||
/ sizeof(asn_DEF_NumericString_tags[0]) - 1,
|
||||
asn_DEF_NumericString_tags,
|
||||
sizeof(asn_DEF_NumericString_tags)
|
||||
/ sizeof(asn_DEF_NumericString_tags[0]),
|
||||
{
|
||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
|
||||
&asn_DEF_NumericString_per_constraints,
|
||||
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
|
||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
|
||||
0,
|
||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
|
||||
NumericString_constraint
|
||||
},
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
int
|
||||
NumericString_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const NumericString_t *st = (const NumericString_t *)sptr;
|
||||
|
||||
if(st && st->buf) {
|
||||
uint8_t *buf = st->buf;
|
||||
uint8_t *end = buf + st->size;
|
||||
|
||||
/*
|
||||
* Check the alphabet of the NumericString.
|
||||
* ASN.1:1984 (X.409)
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
switch(*buf) {
|
||||
case 0x20:
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
continue;
|
||||
}
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: value byte %ld (%d) "
|
||||
"not in NumericString alphabet (%s:%d)",
|
||||
td->name,
|
||||
(long)((buf - st->buf) + 1),
|
||||
*buf,
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: value not given (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user