blob: db010729e8831e2cd026828c616c934ac445e087 [file] [log] [blame]
Lev Walkind9221842017-08-22 01:44:56 -07001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <assert.h>
6
7#include "asn1_ref.h"
8#include "asn1_buffer.h"
9#include "asn1_namespace.h"
10
11static void (*_add_standard_namespaces_cb)(asn1_namespace_t *);
12
13void
14asn1_namespace_add_standard_namespaces_callback(
15 void (*cb)(asn1_namespace_t *)) {
16 _add_standard_namespaces_cb = cb;
17}
18
19asn1_namespace_t *
20asn1_namespace_new() {
21 asn1_namespace_t *ns = calloc(1, sizeof(*ns));
22
23 if(_add_standard_namespaces_cb) {
24 _add_standard_namespaces_cb(ns);
25 }
26
27 return ns;
28}
29
30void
31asn1_namespace_free(asn1_namespace_t *ns) {
32 if(ns) {
33 for(size_t i = 0; i < ns->elements_count; i++) {
34 switch(ns->elements[i].selector) {
35 case NAM_SPACE:
36 break;
37 case NAM_SYMBOL:
38 free(ns->elements[i].u.symbol.identifier);
39 break;
40 }
41 }
42 free(ns->elements);
43 free(ns);
44 }
45}
46
47asn1_namespace_t *
48asn1_namespace_clone(const asn1_namespace_t *old_ns) {
49 asn1_namespace_t *new_ns = calloc(1, sizeof(*new_ns));
50
51 for(size_t i = 0; i < old_ns->elements_count; i++) {
52 switch(old_ns->elements[i].selector) {
53 case NAM_SPACE:
54 asn1_namespace_add_module(new_ns,
55 old_ns->elements[i].u.space.module,
56 old_ns->elements[i].u.space.stop_search);
57 break;
58 case NAM_SYMBOL:
59 asn1_namespace_add_symbol(
60 new_ns, old_ns->elements[i].u.symbol.opt_governor,
61 old_ns->elements[i].u.symbol.identifier,
62 old_ns->elements[i].u.symbol.resolution);
63 break;
64 }
65 }
66
67 return new_ns;
68}
69
70static size_t
71_add_element(asn1_namespace_t *ns) {
72 size_t idx = ns->elements_count;
73
74 if(ns->elements_count >= ns->elements_size) {
75 size_t elc = ns->elements_size ? ns->elements_size * 2 : 4;
76 ns->elements = realloc(ns->elements, sizeof(ns->elements[0]) * elc);
77 ns->elements_size = elc;
78 }
79
80 ns->elements_count++;
81 return idx;
82}
83
84void
85asn1_namespace_add_symbol(asn1_namespace_t *ns,
86 struct asn1p_ref_s *opt_governor,
87 const char *identifier,
88 struct asn1p_expr_s *resolved_argument) {
89 size_t idx = _add_element(ns);
90
91 ns->elements[idx].selector = NAM_SYMBOL;
92 ns->elements[idx].u.symbol.opt_governor = opt_governor;
93 ns->elements[idx].u.symbol.identifier = strdup(identifier);
94 ns->elements[idx].u.symbol.resolution = resolved_argument;
95}
96
97asn1_namespace_t *
98asn1_namespace_new_from_module(struct asn1p_module_s *module, int stop_search) {
99 asn1_namespace_t *ns = asn1_namespace_new();
100 asn1_namespace_add_module(ns, module, stop_search);
101 return ns;
102}
103
104void
105asn1_namespace_add_module(asn1_namespace_t *ns, struct asn1p_module_s *module,
106 int stop_search) {
107 size_t idx = _add_element(ns);
108
109 ns->elements[idx].selector = NAM_SPACE,
110 ns->elements[idx].u.space.module = module;
111 ns->elements[idx].u.space.stop_search = stop_search;
112}
113
114const char *
115asn1_namespace_string(const asn1_namespace_t *ns) {
116 static abuf ab;
117
118 abuf_clear(&ab);
119
120 if(ns) {
121 abuf_str(&ab, "{");
122 for(size_t i = 0; i < ns->elements_count; i++) {
123 if(i) abuf_str(&ab, ",");
124 switch(ns->elements[i].selector) {
125 case NAM_SPACE:
126 abuf_printf(
127 &ab, "M:\"%s\"%s",
128 *(const char *const *)ns->elements[i].u.space.module,
129 ns->elements[i].u.space.stop_search ? "!" : "");
130 break;
131 case NAM_SYMBOL:
132 abuf_printf(&ab, "S:\"%s%s%s\"",
133 ns->elements[i].u.symbol.opt_governor
134 ? asn1p_ref_string(
135 ns->elements[i].u.symbol.opt_governor)
136 : "",
137 ns->elements[i].u.symbol.opt_governor ? ":" : "",
138 ns->elements[i].u.symbol.identifier);
139 break;
140 }
141 }
142 abuf_str(&ab, "}");
143 return ab.buffer;
144 } else {
145 return "<no namespace>";
146 }
147}
148