diff options
author | Lev Walkin <vlm@lionet.info> | 2004-09-13 08:26:57 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2004-09-13 08:26:57 +0000 |
commit | d563d397686b3f9d78ee22ba6a2bd83d29807dd4 (patch) | |
tree | 45ff7370902dea337dac742ca7ee8b3e98d7f12d | |
parent | 9b48a05d372b9e5e1d58b65c2b74cfb2ba1d61ad (diff) |
added type2any and any2type conversion routines
-rw-r--r-- | skeletons/ANY.c | 115 | ||||
-rw-r--r-- | skeletons/ANY.h | 7 |
2 files changed, 120 insertions, 2 deletions
diff --git a/skeletons/ANY.c b/skeletons/ANY.c index 92b209d9..389452cd 100644 --- a/skeletons/ANY.c +++ b/skeletons/ANY.c @@ -14,9 +14,120 @@ asn1_TYPE_descriptor_t asn1_DEF_ANY = { OCTET_STRING_print, OCTET_STRING_free, 0, /* Use generic outmost tag fetcher */ - 0, - 0, /* No tags may be overridden */ + 0, 0, 0, 0, -1, /* Both ways are fine (primitive and constructed) */ 0, 0, /* No members */ (void *)1 /* Special indicator that this is an ANY type */ }; + + +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); + +int +ANY_fromType(ANY_t *st, asn1_TYPE_descriptor_t *td, void *sptr) { + struct _callback_arg arg; + der_enc_rval_t erval; + + 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(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(asn1_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 *)MALLOC(sizeof(*st)); + if(st) { + *st = tmp; + return st; + } else { + FREEMEM(tmp.buf); + return 0; + } +} + +int +ANY_to_type(ANY_t *st, asn1_TYPE_descriptor_t *td, void **struct_ptr) { + ber_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(td, (void **)&newst, st->buf, st->size); + if(rval.code == RC_OK) { + *struct_ptr = newst; + return 0; + } else { + /* Remove possibly partially decoded data. */ + td->free_struct(td, newst, 0); + return -1; + } +} + +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; + (void *)arg->buffer = p; + arg->size = nsize; + } + + memcpy(arg->buffer + arg->offset, buffer, size); + arg->offset += size; + assert(arg->offset < arg->size); + + return 0; +} + diff --git a/skeletons/ANY.h b/skeletons/ANY.h index 0f10e101..719b3a99 100644 --- a/skeletons/ANY.h +++ b/skeletons/ANY.h @@ -26,6 +26,13 @@ asn_struct_free_f ANY_free; * Handy conversion routines. * ******************************/ +/* Convert another ASN.1 type into the ANY. This implies DER encoding. */ +int ANY_fromType(ANY_t *, asn1_TYPE_descriptor_t *td, void *struct_ptr); +ANY_t *ANY_new_fromType(asn1_TYPE_descriptor_t *td, void *struct_ptr); + +/* Convert the contents of the ANY type into the specified type. */ +int ANY_to_type(ANY_t *, asn1_TYPE_descriptor_t *td, void **struct_ptr); + #define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size)) #define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf((buf), (size)) |