SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / ANY_ber.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <ANY.h>
8 #include <errno.h>
9
10 struct _callback_arg {
11     uint8_t *buffer;
12     size_t offset;
13     size_t size;
14 };
15
16 static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
17     struct _callback_arg *arg = (struct _callback_arg *)key;
18
19     if((arg->offset + size) >= arg->size) {
20         size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
21         void *p = REALLOC(arg->buffer, nsize);
22         if(!p) return -1;
23         arg->buffer = (uint8_t *)p;
24         arg->size = nsize;
25     }
26
27     memcpy(arg->buffer + arg->offset, buffer, size);
28     arg->offset += size;
29     assert(arg->offset < arg->size);
30
31     return 0;
32 }
33
34 int
35 ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
36     struct _callback_arg arg;
37     asn_enc_rval_t erval = {0,0,0};
38
39     if(!st || !td) {
40         errno = EINVAL;
41         return -1;
42     }
43
44     if(!sptr) {
45         if(st->buf) FREEMEM(st->buf);
46         st->size = 0;
47         return 0;
48     }
49
50     arg.offset = arg.size = 0;
51     arg.buffer = 0;
52
53     erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
54     if(erval.encoded == -1) {
55         if(arg.buffer) FREEMEM(arg.buffer);
56         return -1;
57     }
58     assert((size_t)erval.encoded == arg.offset);
59
60     if(st->buf) FREEMEM(st->buf);
61     st->buf = arg.buffer;
62     st->size = arg.offset;
63
64     return 0;
65 }
66
67 ANY_t *
68 ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
69     ANY_t tmp;
70     ANY_t *st;
71
72     if(!td || !sptr) {
73         errno = EINVAL;
74         return 0;
75     }
76
77     memset(&tmp, 0, sizeof(tmp));
78
79     if(ANY_fromType(&tmp, td, sptr)) return 0;
80
81     st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
82     if(st) {
83         *st = tmp;
84         return st;
85     } else {
86         FREEMEM(tmp.buf);
87         return 0;
88     }
89 }
90
91 int
92 ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
93     asn_dec_rval_t rval;
94     void *newst = 0;
95
96     if(!st || !td || !struct_ptr) {
97         errno = EINVAL;
98         return -1;
99     }
100
101     if(st->buf == 0) {
102         /* Nothing to convert, make it empty. */
103         *struct_ptr = (void *)0;
104         return 0;
105     }
106
107     rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
108     if(rval.code == RC_OK) {
109         *struct_ptr = newst;
110         return 0;
111     } else {
112         /* Remove possibly partially decoded data. */
113         ASN_STRUCT_FREE(*td, newst);
114         return -1;
115     }
116 }