Lev Walkin | d922184 | 2017-08-22 01:44:56 -0700 | [diff] [blame] | 1 | #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 | |
| 11 | static void (*_add_standard_namespaces_cb)(asn1_namespace_t *); |
| 12 | |
| 13 | void |
| 14 | asn1_namespace_add_standard_namespaces_callback( |
| 15 | void (*cb)(asn1_namespace_t *)) { |
| 16 | _add_standard_namespaces_cb = cb; |
| 17 | } |
| 18 | |
| 19 | asn1_namespace_t * |
| 20 | asn1_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 | |
| 30 | void |
| 31 | asn1_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 | |
| 47 | asn1_namespace_t * |
| 48 | asn1_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 | |
| 70 | static 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 | |
| 84 | void |
| 85 | asn1_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 | |
| 97 | asn1_namespace_t * |
| 98 | asn1_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 | |
| 104 | void |
| 105 | asn1_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 | |
| 114 | const char * |
| 115 | asn1_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 | |