blob: ae19ab5db9f92b07cb0dc6aa1a5bd8e927cf873d [file] [log] [blame]
Lev Walkina737f3b2004-09-02 12:11:47 +00001/*-
2 * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00005#include <asn_internal.h>
Lev Walkina737f3b2004-09-02 12:11:47 +00006#include <ANY.h>
7#include <assert.h>
8#include <errno.h>
9
Lev Walkin5e033762004-09-29 13:26:15 +000010asn_TYPE_descriptor_t asn_DEF_ANY = {
Lev Walkina737f3b2004-09-02 12:11:47 +000011 "ANY",
Lev Walkina9cc46e2004-09-22 16:06:28 +000012 OCTET_STRING_free,
13 OCTET_STRING_print,
Lev Walkina737f3b2004-09-02 12:11:47 +000014 asn_generic_no_constraint,
15 OCTET_STRING_decode_ber,
16 OCTET_STRING_encode_der,
Lev Walkina9cc46e2004-09-22 16:06:28 +000017 0, /* Not implemented yet */
18 ANY_encode_xer,
Lev Walkina737f3b2004-09-02 12:11:47 +000019 0, /* Use generic outmost tag fetcher */
Lev Walkind563d392004-09-13 08:26:57 +000020 0, 0, 0, 0,
Lev Walkina737f3b2004-09-02 12:11:47 +000021 0, 0, /* No members */
Lev Walkin8e8078a2004-09-26 13:10:40 +000022 (void *)2 /* Special indicator that this is an ANY type */
Lev Walkina737f3b2004-09-02 12:11:47 +000023};
Lev Walkind563d392004-09-13 08:26:57 +000024
25
Lev Walkina9cc46e2004-09-22 16:06:28 +000026asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +000027ANY_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +000028 int ilevel, enum xer_encoder_flags_e flags,
29 asn_app_consume_bytes_f *cb, void *app_key) {
30
Lev Walkincc6a9102004-09-23 22:06:26 +000031 if(flags & XER_F_CANONICAL) {
32 /*
33 * Canonical XER-encoding of ANY type is not supported.
34 */
35 _ASN_ENCODE_FAILED;
36 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000037
Lev Walkincc6a9102004-09-23 22:06:26 +000038 /* Dump as binary */
39 return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
Lev Walkina9cc46e2004-09-22 16:06:28 +000040}
41
Lev Walkind563d392004-09-13 08:26:57 +000042struct _callback_arg {
43 uint8_t *buffer;
44 size_t offset;
45 size_t size;
46};
47
48static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
49
50int
Lev Walkin5e033762004-09-29 13:26:15 +000051ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
Lev Walkind563d392004-09-13 08:26:57 +000052 struct _callback_arg arg;
Lev Walkina9cc46e2004-09-22 16:06:28 +000053 asn_enc_rval_t erval;
Lev Walkind563d392004-09-13 08:26:57 +000054
55 if(!st || !td) {
56 errno = EINVAL;
57 return -1;
58 }
59
60 if(!sptr) {
61 if(st->buf) FREEMEM(st->buf);
62 st->size = 0;
63 return 0;
64 }
65
66 arg.offset = arg.size = 0;
67 arg.buffer = 0;
68
69 erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
70 if(erval.encoded == -1) {
71 if(arg.buffer) FREEMEM(arg.buffer);
72 return -1;
73 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000074 assert((size_t)erval.encoded == arg.offset);
Lev Walkind563d392004-09-13 08:26:57 +000075
76 if(st->buf) FREEMEM(st->buf);
77 st->buf = arg.buffer;
78 st->size = arg.offset;
79
80 return 0;
81}
82
83ANY_t *
Lev Walkin5e033762004-09-29 13:26:15 +000084ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
Lev Walkind563d392004-09-13 08:26:57 +000085 ANY_t tmp;
86 ANY_t *st;
87
88 if(!td || !sptr) {
89 errno = EINVAL;
90 return 0;
91 }
92
93 memset(&tmp, 0, sizeof(tmp));
94
95 if(ANY_fromType(&tmp, td, sptr)) return 0;
96
97 st = (ANY_t *)MALLOC(sizeof(*st));
98 if(st) {
99 *st = tmp;
100 return st;
101 } else {
102 FREEMEM(tmp.buf);
103 return 0;
104 }
105}
106
107int
Lev Walkin5e033762004-09-29 13:26:15 +0000108ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
Lev Walkind563d392004-09-13 08:26:57 +0000109 ber_dec_rval_t rval;
110 void *newst = 0;
111
112 if(!st || !td || !struct_ptr) {
113 errno = EINVAL;
114 return -1;
115 }
116
117 if(st->buf == 0) {
118 /* Nothing to convert, make it empty. */
119 *struct_ptr = (void *)0;
120 return 0;
121 }
122
Lev Walkin5e033762004-09-29 13:26:15 +0000123 rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
Lev Walkind563d392004-09-13 08:26:57 +0000124 if(rval.code == RC_OK) {
125 *struct_ptr = newst;
126 return 0;
127 } else {
128 /* Remove possibly partially decoded data. */
129 td->free_struct(td, newst, 0);
130 return -1;
131 }
132}
133
134static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
135 struct _callback_arg *arg = (struct _callback_arg *)key;
136
137 if((arg->offset + size) >= arg->size) {
138 size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
139 void *p = REALLOC(arg->buffer, nsize);
140 if(!p) return -1;
Lev Walkin8e8078a2004-09-26 13:10:40 +0000141 arg->buffer = (uint8_t *)p;
Lev Walkind563d392004-09-13 08:26:57 +0000142 arg->size = nsize;
143 }
144
145 memcpy(arg->buffer + arg->offset, buffer, size);
146 arg->offset += size;
147 assert(arg->offset < arg->size);
148
149 return 0;
150}
151