blob: 73702444a7ed4b97fa6b0916e57b72abb46c115e [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>
Lev Walkina737f3b2004-09-02 12:11:47 +00007#include <errno.h>
8
Lev Walkinbbd93252004-10-12 05:57:23 +00009static asn_OCTET_STRING_specifics_t asn_DEF_ANY_specs = {
10 sizeof(ANY_t),
11 offsetof(ANY_t, _asn_ctx),
12 2 /* Special indicator that this is an ANY type */
13};
Lev Walkin5e033762004-09-29 13:26:15 +000014asn_TYPE_descriptor_t asn_DEF_ANY = {
Lev Walkina737f3b2004-09-02 12:11:47 +000015 "ANY",
Lev Walkindc06f6b2004-10-20 15:50:55 +000016 "ANY",
Lev Walkina9cc46e2004-09-22 16:06:28 +000017 OCTET_STRING_free,
18 OCTET_STRING_print,
Lev Walkina737f3b2004-09-02 12:11:47 +000019 asn_generic_no_constraint,
20 OCTET_STRING_decode_ber,
21 OCTET_STRING_encode_der,
Lev Walkindc06f6b2004-10-20 15:50:55 +000022 OCTET_STRING_decode_xer_hex,
Lev Walkina9cc46e2004-09-22 16:06:28 +000023 ANY_encode_xer,
Lev Walkina737f3b2004-09-02 12:11:47 +000024 0, /* Use generic outmost tag fetcher */
Lev Walkind563d392004-09-13 08:26:57 +000025 0, 0, 0, 0,
Lev Walkina737f3b2004-09-02 12:11:47 +000026 0, 0, /* No members */
Lev Walkinbbd93252004-10-12 05:57:23 +000027 &asn_DEF_ANY_specs,
Lev Walkina737f3b2004-09-02 12:11:47 +000028};
Lev Walkind563d392004-09-13 08:26:57 +000029
30
Lev Walkina9cc46e2004-09-22 16:06:28 +000031asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +000032ANY_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +000033 int ilevel, enum xer_encoder_flags_e flags,
34 asn_app_consume_bytes_f *cb, void *app_key) {
35
Lev Walkincc6a9102004-09-23 22:06:26 +000036 if(flags & XER_F_CANONICAL) {
37 /*
38 * Canonical XER-encoding of ANY type is not supported.
39 */
40 _ASN_ENCODE_FAILED;
41 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000042
Lev Walkincc6a9102004-09-23 22:06:26 +000043 /* Dump as binary */
44 return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
Lev Walkina9cc46e2004-09-22 16:06:28 +000045}
46
Lev Walkind563d392004-09-13 08:26:57 +000047struct _callback_arg {
48 uint8_t *buffer;
49 size_t offset;
50 size_t size;
51};
52
53static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
54
55int
Lev Walkin5e033762004-09-29 13:26:15 +000056ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
Lev Walkind563d392004-09-13 08:26:57 +000057 struct _callback_arg arg;
Lev Walkina9cc46e2004-09-22 16:06:28 +000058 asn_enc_rval_t erval;
Lev Walkind563d392004-09-13 08:26:57 +000059
60 if(!st || !td) {
61 errno = EINVAL;
62 return -1;
63 }
64
65 if(!sptr) {
66 if(st->buf) FREEMEM(st->buf);
67 st->size = 0;
68 return 0;
69 }
70
71 arg.offset = arg.size = 0;
72 arg.buffer = 0;
73
74 erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
75 if(erval.encoded == -1) {
76 if(arg.buffer) FREEMEM(arg.buffer);
77 return -1;
78 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000079 assert((size_t)erval.encoded == arg.offset);
Lev Walkind563d392004-09-13 08:26:57 +000080
81 if(st->buf) FREEMEM(st->buf);
82 st->buf = arg.buffer;
83 st->size = arg.offset;
84
85 return 0;
86}
87
88ANY_t *
Lev Walkin5e033762004-09-29 13:26:15 +000089ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
Lev Walkind563d392004-09-13 08:26:57 +000090 ANY_t tmp;
91 ANY_t *st;
92
93 if(!td || !sptr) {
94 errno = EINVAL;
95 return 0;
96 }
97
98 memset(&tmp, 0, sizeof(tmp));
99
100 if(ANY_fromType(&tmp, td, sptr)) return 0;
101
Lev Walkin40fecb02005-01-22 00:11:28 +0000102 st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
Lev Walkind563d392004-09-13 08:26:57 +0000103 if(st) {
104 *st = tmp;
105 return st;
106 } else {
107 FREEMEM(tmp.buf);
108 return 0;
109 }
110}
111
112int
Lev Walkin5e033762004-09-29 13:26:15 +0000113ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
Lev Walkindc06f6b2004-10-20 15:50:55 +0000114 asn_dec_rval_t rval;
Lev Walkind563d392004-09-13 08:26:57 +0000115 void *newst = 0;
116
117 if(!st || !td || !struct_ptr) {
118 errno = EINVAL;
119 return -1;
120 }
121
122 if(st->buf == 0) {
123 /* Nothing to convert, make it empty. */
124 *struct_ptr = (void *)0;
125 return 0;
126 }
127
Lev Walkin5e033762004-09-29 13:26:15 +0000128 rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
Lev Walkind563d392004-09-13 08:26:57 +0000129 if(rval.code == RC_OK) {
130 *struct_ptr = newst;
131 return 0;
132 } else {
133 /* Remove possibly partially decoded data. */
134 td->free_struct(td, newst, 0);
135 return -1;
136 }
137}
138
139static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
140 struct _callback_arg *arg = (struct _callback_arg *)key;
141
142 if((arg->offset + size) >= arg->size) {
143 size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
144 void *p = REALLOC(arg->buffer, nsize);
145 if(!p) return -1;
Lev Walkin8e8078a2004-09-26 13:10:40 +0000146 arg->buffer = (uint8_t *)p;
Lev Walkind563d392004-09-13 08:26:57 +0000147 arg->size = nsize;
148 }
149
150 memcpy(arg->buffer + arg->offset, buffer, size);
151 arg->offset += size;
152 assert(arg->offset < arg->size);
153
154 return 0;
155}
156