Mercurial > hg > piper-cpp
comparison ext/serd/src/env.c @ 226:c5cdc9e6a4bf
Add these external library files
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Fri, 09 Jun 2017 16:41:31 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
225:025b3e2f7c17 | 226:c5cdc9e6a4bf |
---|---|
1 /* | |
2 Copyright 2011-2016 David Robillard <http://drobilla.net> | |
3 | |
4 Permission to use, copy, modify, and/or distribute this software for any | |
5 purpose with or without fee is hereby granted, provided that the above | |
6 copyright notice and this permission notice appear in all copies. | |
7 | |
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #include "serd_internal.h" | |
18 | |
19 #include <stdlib.h> | |
20 #include <string.h> | |
21 | |
22 typedef struct { | |
23 SerdNode name; | |
24 SerdNode uri; | |
25 } SerdPrefix; | |
26 | |
27 struct SerdEnvImpl { | |
28 SerdPrefix* prefixes; | |
29 size_t n_prefixes; | |
30 SerdNode base_uri_node; | |
31 SerdURI base_uri; | |
32 }; | |
33 | |
34 SERD_API | |
35 SerdEnv* | |
36 serd_env_new(const SerdNode* base_uri) | |
37 { | |
38 SerdEnv* env = (SerdEnv*)calloc(sizeof(struct SerdEnvImpl), 1); | |
39 if (env && base_uri) { | |
40 serd_env_set_base_uri(env, base_uri); | |
41 } | |
42 return env; | |
43 } | |
44 | |
45 SERD_API | |
46 void | |
47 serd_env_free(SerdEnv* env) | |
48 { | |
49 for (size_t i = 0; i < env->n_prefixes; ++i) { | |
50 serd_node_free(&env->prefixes[i].name); | |
51 serd_node_free(&env->prefixes[i].uri); | |
52 } | |
53 free(env->prefixes); | |
54 serd_node_free(&env->base_uri_node); | |
55 free(env); | |
56 } | |
57 | |
58 SERD_API | |
59 const SerdNode* | |
60 serd_env_get_base_uri(const SerdEnv* env, | |
61 SerdURI* out) | |
62 { | |
63 if (out) { | |
64 *out = env->base_uri; | |
65 } | |
66 return &env->base_uri_node; | |
67 } | |
68 | |
69 SERD_API | |
70 SerdStatus | |
71 serd_env_set_base_uri(SerdEnv* env, | |
72 const SerdNode* uri_node) | |
73 { | |
74 if (!env || !uri_node) { | |
75 return SERD_ERR_BAD_ARG; | |
76 } | |
77 | |
78 // Resolve base URI and create a new node and URI for it | |
79 SerdURI base_uri; | |
80 SerdNode base_uri_node = serd_node_new_uri_from_node( | |
81 uri_node, &env->base_uri, &base_uri); | |
82 | |
83 if (base_uri_node.buf) { | |
84 // Replace the current base URI | |
85 serd_node_free(&env->base_uri_node); | |
86 env->base_uri_node = base_uri_node; | |
87 env->base_uri = base_uri; | |
88 return SERD_SUCCESS; | |
89 } | |
90 return SERD_ERR_BAD_ARG; | |
91 } | |
92 | |
93 static inline SerdPrefix* | |
94 serd_env_find(const SerdEnv* env, | |
95 const uint8_t* name, | |
96 size_t name_len) | |
97 { | |
98 for (size_t i = 0; i < env->n_prefixes; ++i) { | |
99 const SerdNode* const prefix_name = &env->prefixes[i].name; | |
100 if (prefix_name->n_bytes == name_len) { | |
101 if (!memcmp(prefix_name->buf, name, name_len)) { | |
102 return &env->prefixes[i]; | |
103 } | |
104 } | |
105 } | |
106 return NULL; | |
107 } | |
108 | |
109 static void | |
110 serd_env_add(SerdEnv* env, | |
111 const SerdNode* name, | |
112 const SerdNode* uri) | |
113 { | |
114 SerdPrefix* const prefix = serd_env_find(env, name->buf, name->n_bytes); | |
115 if (prefix) { | |
116 SerdNode old_prefix_uri = prefix->uri; | |
117 prefix->uri = serd_node_copy(uri); | |
118 serd_node_free(&old_prefix_uri); | |
119 } else { | |
120 env->prefixes = (SerdPrefix*)realloc( | |
121 env->prefixes, (++env->n_prefixes) * sizeof(SerdPrefix)); | |
122 env->prefixes[env->n_prefixes - 1].name = serd_node_copy(name); | |
123 env->prefixes[env->n_prefixes - 1].uri = serd_node_copy(uri); | |
124 } | |
125 } | |
126 | |
127 SERD_API | |
128 SerdStatus | |
129 serd_env_set_prefix(SerdEnv* env, | |
130 const SerdNode* name, | |
131 const SerdNode* uri_node) | |
132 { | |
133 if (!name->buf || uri_node->type != SERD_URI) { | |
134 return SERD_ERR_BAD_ARG; | |
135 } else if (serd_uri_string_has_scheme(uri_node->buf)) { | |
136 // Set prefix to absolute URI | |
137 serd_env_add(env, name, uri_node); | |
138 } else { | |
139 // Resolve relative URI and create a new node and URI for it | |
140 SerdURI abs_uri; | |
141 SerdNode abs_uri_node = serd_node_new_uri_from_node( | |
142 uri_node, &env->base_uri, &abs_uri); | |
143 | |
144 // Set prefix to resolved (absolute) URI | |
145 serd_env_add(env, name, &abs_uri_node); | |
146 serd_node_free(&abs_uri_node); | |
147 } | |
148 return SERD_SUCCESS; | |
149 } | |
150 | |
151 SERD_API | |
152 SerdStatus | |
153 serd_env_set_prefix_from_strings(SerdEnv* env, | |
154 const uint8_t* name, | |
155 const uint8_t* uri) | |
156 { | |
157 const SerdNode name_node = serd_node_from_string(SERD_LITERAL, name); | |
158 const SerdNode uri_node = serd_node_from_string(SERD_URI, uri); | |
159 | |
160 return serd_env_set_prefix(env, &name_node, &uri_node); | |
161 } | |
162 | |
163 static inline bool | |
164 is_nameChar(const uint8_t c) | |
165 { | |
166 return is_alpha(c) || is_digit(c) || c == '_'; | |
167 } | |
168 | |
169 /** | |
170 Return true iff `buf` is a valid prefixed name suffix. | |
171 TODO: This is more strict than it should be. | |
172 */ | |
173 static inline bool | |
174 is_name(const uint8_t* buf, size_t len) | |
175 { | |
176 for (size_t i = 0; i < len; ++i) { | |
177 if (!is_nameChar(buf[i])) { | |
178 return false; | |
179 } | |
180 } | |
181 return true; | |
182 } | |
183 | |
184 SERD_API | |
185 bool | |
186 serd_env_qualify(const SerdEnv* env, | |
187 const SerdNode* uri, | |
188 SerdNode* prefix_name, | |
189 SerdChunk* suffix) | |
190 { | |
191 for (size_t i = 0; i < env->n_prefixes; ++i) { | |
192 const SerdNode* const prefix_uri = &env->prefixes[i].uri; | |
193 if (uri->n_bytes >= prefix_uri->n_bytes) { | |
194 if (!strncmp((const char*)uri->buf, | |
195 (const char*)prefix_uri->buf, | |
196 prefix_uri->n_bytes)) { | |
197 *prefix_name = env->prefixes[i].name; | |
198 suffix->buf = uri->buf + prefix_uri->n_bytes; | |
199 suffix->len = uri->n_bytes - prefix_uri->n_bytes; | |
200 if (is_name(suffix->buf, suffix->len)) { | |
201 return true; | |
202 } | |
203 } | |
204 } | |
205 } | |
206 return false; | |
207 } | |
208 | |
209 SERD_API | |
210 SerdStatus | |
211 serd_env_expand(const SerdEnv* env, | |
212 const SerdNode* qname, | |
213 SerdChunk* uri_prefix, | |
214 SerdChunk* uri_suffix) | |
215 { | |
216 const uint8_t* const colon = (const uint8_t*)memchr( | |
217 qname->buf, ':', qname->n_bytes + 1); | |
218 if (!colon) { | |
219 return SERD_ERR_BAD_ARG; // Invalid qname | |
220 } | |
221 | |
222 const size_t name_len = colon - qname->buf; | |
223 const SerdPrefix* const prefix = serd_env_find(env, qname->buf, name_len); | |
224 if (prefix) { | |
225 uri_prefix->buf = prefix->uri.buf; | |
226 uri_prefix->len = prefix->uri.n_bytes; | |
227 uri_suffix->buf = colon + 1; | |
228 uri_suffix->len = qname->n_bytes - (colon - qname->buf) - 1; | |
229 return SERD_SUCCESS; | |
230 } | |
231 return SERD_ERR_NOT_FOUND; | |
232 } | |
233 | |
234 SERD_API | |
235 SerdNode | |
236 serd_env_expand_node(const SerdEnv* env, | |
237 const SerdNode* node) | |
238 { | |
239 switch (node->type) { | |
240 case SERD_CURIE: { | |
241 SerdChunk prefix; | |
242 SerdChunk suffix; | |
243 if (serd_env_expand(env, node, &prefix, &suffix)) { | |
244 return SERD_NODE_NULL; | |
245 } | |
246 const size_t len = prefix.len + suffix.len; | |
247 uint8_t* buf = (uint8_t*)malloc(len + 1); | |
248 SerdNode ret = { buf, len, 0, 0, SERD_URI }; | |
249 snprintf((char*)buf, len + 1, "%s%s", prefix.buf, suffix.buf); | |
250 ret.n_chars = serd_strlen(buf, NULL, NULL); | |
251 return ret; | |
252 } | |
253 case SERD_URI: { | |
254 SerdURI ignored; | |
255 return serd_node_new_uri_from_node(node, &env->base_uri, &ignored); | |
256 } | |
257 default: | |
258 return SERD_NODE_NULL; | |
259 } | |
260 } | |
261 | |
262 SERD_API | |
263 void | |
264 serd_env_foreach(const SerdEnv* env, | |
265 SerdPrefixSink func, | |
266 void* handle) | |
267 { | |
268 for (size_t i = 0; i < env->n_prefixes; ++i) { | |
269 func(handle, &env->prefixes[i].name, &env->prefixes[i].uri); | |
270 } | |
271 } |