]>
Commit | Line | Data |
---|---|---|
f3df4c03 A |
1 | /* |
2 | * Copyright (c) 2007-2013 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | #include <asl_object.h> | |
24 | #include <asl_core.h> | |
25 | #include <asl_private.h> | |
26 | #include <asl_msg.h> | |
27 | #include <asl_msg_list.h> | |
28 | #include <asl_client.h> | |
29 | #include <asl_store.h> | |
30 | #include <asl_file.h> | |
31 | #include <dispatch/dispatch.h> | |
32 | #include <libkern/OSAtomic.h> | |
33 | ||
34 | static const asl_jump_table_t *asl_jump[ASL_TYPE_COUNT]; | |
35 | static dispatch_once_t asl_object_once; | |
36 | ||
37 | static void | |
38 | _asl_object_init(void) | |
39 | { | |
40 | asl_jump[ASL_TYPE_MSG] = asl_msg_jump_table(); | |
41 | asl_jump[ASL_TYPE_QUERY] = asl_msg_jump_table(); | |
42 | asl_jump[ASL_TYPE_LIST] = asl_msg_list_jump_table(); | |
43 | asl_jump[ASL_TYPE_FILE] = asl_file_jump_table(); | |
44 | asl_jump[ASL_TYPE_STORE] = asl_store_jump_table(); | |
45 | asl_jump[ASL_TYPE_CLIENT] = asl_client_jump_table(); | |
46 | } | |
47 | ||
48 | #pragma mark - | |
49 | #pragma mark asl_object | |
50 | ||
51 | int | |
52 | asl_object_set_key_val_op(asl_object_private_t *obj, const char *key, const char *val, uint16_t op) | |
53 | { | |
54 | if (obj == NULL) return -1; | |
55 | if (obj->asl_type >= ASL_TYPE_COUNT) return -1; | |
56 | ||
57 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
58 | if (asl_jump[obj->asl_type]->set_key_val_op == NULL) return -1; | |
59 | return asl_jump[obj->asl_type]->set_key_val_op(obj, key, val, op); | |
60 | } | |
61 | ||
62 | void | |
63 | asl_object_unset_key(asl_object_private_t *obj, const char *key) | |
64 | { | |
65 | if (obj == NULL) return; | |
66 | if (obj->asl_type >= ASL_TYPE_COUNT) return; | |
67 | ||
68 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
69 | if (asl_jump[obj->asl_type]->unset_key == NULL) return; | |
70 | asl_jump[obj->asl_type]->unset_key(obj, key); | |
71 | } | |
72 | ||
73 | int | |
74 | asl_object_get_val_op_for_key(asl_object_private_t *obj, const char *key, const char **val, uint16_t *op) | |
75 | { | |
76 | if (obj == NULL) return -1; | |
77 | if (obj->asl_type >= ASL_TYPE_COUNT) return -1; | |
78 | ||
79 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
80 | if (asl_jump[obj->asl_type]->get_val_op_for_key == NULL) return -1; | |
81 | return asl_jump[obj->asl_type]->get_val_op_for_key(obj, key, val, op); | |
82 | } | |
83 | ||
84 | int | |
85 | asl_object_get_key_val_op_at_index(asl_object_private_t *obj, size_t n, const char **key, const char **val, uint16_t *op) | |
86 | { | |
87 | if (obj == NULL) return -1; | |
88 | if (obj->asl_type >= ASL_TYPE_COUNT) return -1; | |
89 | ||
90 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
91 | if (asl_jump[obj->asl_type]->get_key_val_op_at_index == NULL) return -1; | |
92 | return asl_jump[obj->asl_type]->get_key_val_op_at_index(obj, n, key, val, op); | |
93 | } | |
94 | ||
95 | size_t | |
96 | asl_object_count(asl_object_private_t *obj) | |
97 | { | |
98 | if (obj == NULL) return 0; | |
99 | if (obj->asl_type >= ASL_TYPE_COUNT) return 0; | |
100 | ||
101 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
102 | if (asl_jump[obj->asl_type]->count == NULL) return 0; | |
103 | return asl_jump[obj->asl_type]->count(obj); | |
104 | } | |
105 | ||
106 | asl_object_private_t * | |
107 | asl_object_next(asl_object_private_t *obj) | |
108 | { | |
109 | if (obj == NULL) return NULL; | |
110 | if (obj->asl_type >= ASL_TYPE_COUNT) return NULL; | |
111 | ||
112 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
113 | if (asl_jump[obj->asl_type]->next == NULL) return NULL; | |
114 | return asl_jump[obj->asl_type]->next(obj); | |
115 | } | |
116 | ||
117 | asl_object_private_t * | |
118 | asl_object_prev(asl_object_private_t *obj) | |
119 | { | |
120 | if (obj == NULL) return NULL; | |
121 | if (obj->asl_type >= ASL_TYPE_COUNT) return NULL; | |
122 | ||
123 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
124 | if (asl_jump[obj->asl_type]->prev == NULL) return NULL; | |
125 | return asl_jump[obj->asl_type]->prev(obj); | |
126 | } | |
127 | ||
128 | asl_object_private_t * | |
129 | asl_object_get_object_at_index(asl_object_private_t *obj, size_t n) | |
130 | { | |
131 | if (obj == NULL) return NULL; | |
132 | if (obj->asl_type >= ASL_TYPE_COUNT) return NULL; | |
133 | ||
134 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
135 | if (asl_jump[obj->asl_type]->get_object_at_index == NULL) return NULL; | |
136 | return asl_jump[obj->asl_type]->get_object_at_index(obj, n); | |
137 | } | |
138 | ||
139 | void | |
140 | asl_object_set_iteration_index(asl_object_private_t *obj, size_t n) | |
141 | { | |
142 | if (obj == NULL) return; | |
143 | if (obj->asl_type >= ASL_TYPE_COUNT) return; | |
144 | ||
145 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
146 | if (asl_jump[obj->asl_type]->set_iteration_index == NULL) return; | |
147 | return asl_jump[obj->asl_type]->set_iteration_index(obj, n); | |
148 | } | |
149 | ||
150 | void | |
151 | asl_object_remove_object_at_index(asl_object_private_t *obj, size_t n) | |
152 | { | |
153 | if (obj == NULL) return; | |
154 | if (obj->asl_type >= ASL_TYPE_COUNT) return; | |
155 | ||
156 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
157 | if (asl_jump[obj->asl_type]->remove_object_at_index == NULL) return; | |
158 | return asl_jump[obj->asl_type]->remove_object_at_index(obj, n); | |
159 | } | |
160 | ||
161 | void | |
af7d442c | 162 | asl_object_append(asl_object_private_t *obj, asl_object_private_t *newobj, void *addr) |
f3df4c03 | 163 | { |
5222c21d | 164 | uint32_t type = ASL_TYPE_CLIENT; |
f3df4c03 A |
165 | |
166 | if (obj != NULL) type = obj->asl_type; | |
167 | if (type >= ASL_TYPE_COUNT) return; | |
168 | ||
169 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
170 | if (asl_jump[type]->append == NULL) return; | |
af7d442c | 171 | return asl_jump[type]->append(obj, newobj, addr); |
f3df4c03 A |
172 | } |
173 | ||
174 | void | |
175 | asl_object_prepend(asl_object_private_t *obj, asl_object_private_t *newobj) | |
176 | { | |
177 | if (obj == NULL) return; | |
178 | if (obj->asl_type >= ASL_TYPE_COUNT) return; | |
179 | ||
180 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
181 | if (asl_jump[obj->asl_type]->prepend == NULL) return; | |
182 | return asl_jump[obj->asl_type]->prepend(obj, newobj); | |
183 | } | |
184 | ||
185 | asl_object_private_t * | |
186 | asl_object_search(asl_object_private_t *obj, asl_object_private_t *query) | |
187 | { | |
188 | /* default to asl_client_search for obj == NULL */ | |
189 | if (obj == NULL) return (asl_object_private_t *)asl_client_search(NULL, (asl_msg_t *)query); | |
190 | if (obj->asl_type >= ASL_TYPE_COUNT) return NULL; | |
191 | ||
192 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
193 | if (asl_jump[obj->asl_type]->search == NULL) return NULL; | |
194 | return asl_jump[obj->asl_type]->search(obj, query); | |
195 | } | |
196 | ||
197 | asl_object_private_t * | |
198 | asl_object_match(asl_object_private_t *obj, asl_object_private_t *qlist, size_t *last, size_t start, size_t count, uint32_t duration, int32_t dir) | |
199 | { | |
200 | /* default to asl_client_match for obj == NULL */ | |
201 | if (obj == NULL) return (asl_object_private_t *)asl_client_match(NULL, (asl_msg_list_t *)qlist, last, start, count, duration, dir); | |
202 | if (obj->asl_type >= ASL_TYPE_COUNT) return NULL; | |
203 | ||
204 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
205 | if (asl_jump[obj->asl_type]->match == NULL) return NULL; | |
206 | return asl_jump[obj->asl_type]->match(obj, qlist, last, start, count, duration, dir); | |
207 | } | |
208 | ||
209 | asl_object_t | |
210 | asl_retain(asl_object_t obj) | |
211 | { | |
212 | asl_object_private_t *oo = (asl_object_private_t *)obj; | |
213 | if (oo == NULL) return NULL; | |
214 | ||
215 | OSAtomicIncrement32Barrier(&(oo->refcount)); | |
216 | return obj; | |
217 | } | |
218 | ||
219 | void | |
220 | asl_release(asl_object_t obj) | |
221 | { | |
222 | asl_object_private_t *oo = (asl_object_private_t *)obj; | |
223 | if (oo == NULL) return; | |
224 | if (oo->asl_type >= ASL_TYPE_COUNT) return; | |
225 | ||
226 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
227 | if (OSAtomicDecrement32Barrier(&(oo->refcount)) != 0) return; | |
228 | if (asl_jump[oo->asl_type]->dealloc != NULL) asl_jump[oo->asl_type]->dealloc(oo); | |
229 | } | |
230 | ||
231 | asl_object_t | |
232 | asl_new(uint32_t type) | |
233 | { | |
234 | if (type >= ASL_TYPE_COUNT) return NULL; | |
235 | ||
236 | dispatch_once(&asl_object_once, ^{ _asl_object_init(); }); | |
237 | if (asl_jump[type]->alloc == NULL) return NULL; | |
238 | asl_object_t out = (asl_object_t)asl_jump[type]->alloc(type); | |
239 | return out; | |
240 | } | |
241 | ||
242 | #pragma mark - | |
243 | #pragma mark utilities | |
244 | ||
245 | uint32_t | |
246 | asl_get_type(asl_object_t obj) | |
247 | { | |
248 | asl_object_private_t *oo = (asl_object_private_t *)obj; | |
249 | ||
250 | if (oo == NULL) return ASL_TYPE_UNDEF; | |
251 | return (int)oo->asl_type; | |
252 | } | |
253 | ||
254 | const char * | |
255 | asl_get_value_for_key(asl_object_t obj, const char *key) | |
256 | { | |
257 | const char *val = NULL; | |
258 | uint16_t op; | |
259 | ||
260 | asl_object_get_val_op_for_key((asl_object_private_t *)obj, key, &val, &op); | |
261 | return val; | |
262 | } | |
263 | ||
264 | int | |
265 | asl_set(asl_object_t obj, const char *key, const char *val) | |
266 | { | |
267 | asl_object_private_t *oo = (asl_object_private_t *)obj; | |
268 | uint16_t op = 0; | |
269 | ||
270 | if (oo == NULL) return -1; | |
271 | if (oo->asl_type == ASL_TYPE_QUERY) op = (uint32_t)-1; | |
272 | ||
273 | return asl_object_set_key_val_op(oo, key, val, op); | |
274 | } | |
275 | ||
276 | int | |
277 | asl_unset_key(asl_object_t obj, const char *key) | |
278 | { | |
279 | asl_object_unset_key((asl_object_private_t *)obj, key); | |
280 | return 0; | |
281 | } | |
282 | ||
283 | int | |
284 | asl_set_key_val_op(asl_object_t obj, const char *key, const char *val, uint16_t op) | |
285 | { | |
286 | return asl_object_set_key_val_op((asl_object_private_t *)obj, key, val, op); | |
287 | } | |
288 | ||
289 | size_t | |
290 | asl_count(asl_object_t obj) | |
291 | { | |
292 | return asl_object_count((asl_object_private_t *)obj); | |
293 | } | |
294 | ||
295 | asl_object_t | |
296 | asl_get_index(asl_object_t list, size_t index) | |
297 | { | |
298 | return (asl_object_t)asl_object_get_object_at_index((asl_object_private_t *)list, index); | |
299 | } | |
300 | ||
301 | asl_object_t | |
302 | asl_next(asl_object_t obj) | |
303 | { | |
304 | return (asl_object_t)asl_object_next((asl_object_private_t *)obj); | |
305 | } | |
306 | ||
307 | asl_object_t | |
308 | asl_prev(asl_object_t obj) | |
309 | { | |
310 | return (asl_object_t)asl_object_prev((asl_object_private_t *)obj); | |
311 | } | |
312 | ||
313 | void | |
314 | asl_append(asl_object_t a, asl_object_t b) | |
315 | { | |
af7d442c | 316 | asl_object_append((asl_object_private_t *)a, (asl_object_private_t *)b, __builtin_return_address(0)); |
f3df4c03 A |
317 | } |
318 | ||
319 | void | |
320 | asl_prepend(asl_object_t a, asl_object_t b) | |
321 | { | |
322 | asl_object_prepend((asl_object_private_t *)a, (asl_object_private_t *)b); | |
323 | } | |
324 | ||
325 | /* asl_send is implemented as asl_append */ | |
326 | int | |
327 | asl_send(asl_object_t a, asl_object_t b) | |
328 | { | |
af7d442c | 329 | asl_object_append((asl_object_private_t *)a, (asl_object_private_t *)b, __builtin_return_address(0)); |
f3df4c03 A |
330 | return 0; |
331 | } | |
332 | ||
333 | const char * | |
334 | asl_key(asl_object_t obj, uint32_t n) | |
335 | { | |
336 | const char *key = NULL; | |
337 | size_t sn = n; | |
338 | ||
339 | if (asl_object_get_key_val_op_at_index((asl_object_private_t *)obj, sn, &key, NULL, NULL) != 0) return NULL; | |
340 | return key; | |
341 | } | |
342 | ||
343 | const char * | |
344 | asl_get(asl_object_t obj, const char *key) | |
345 | { | |
346 | const char *val = NULL; | |
347 | ||
348 | if (asl_object_get_val_op_for_key((asl_object_private_t *)obj, key, &val, NULL) != 0) return NULL; | |
349 | return val; | |
350 | } | |
351 | ||
352 | int | |
353 | asl_fetch_key_val_op(asl_object_t obj, uint32_t n, const char **key, const char **val, uint32_t *op) | |
354 | { | |
355 | uint16_t op16; | |
356 | size_t sn = n; | |
357 | int status = asl_object_get_key_val_op_at_index((asl_object_private_t *)obj, sn, key, val, &op16); | |
358 | if (status != 0) return status; | |
359 | if (op != NULL) *op = op16; | |
360 | return 0; | |
361 | } | |
362 | ||
363 | int | |
364 | asl_set_query(asl_object_t obj, const char *key, const char *val, uint32_t op) | |
365 | { | |
366 | uint16_t op16 = op; | |
367 | return asl_object_set_key_val_op((asl_object_private_t *)obj, key, val, op16); | |
368 | } | |
369 | ||
370 | int | |
371 | asl_unset(asl_object_t obj, const char *key) | |
372 | { | |
373 | asl_object_unset_key((asl_object_private_t *)obj, key); | |
374 | return 0; | |
375 | } | |
376 | ||
377 | void | |
378 | asl_reset_iteration(asl_object_t obj, size_t position) | |
379 | { | |
380 | asl_object_set_iteration_index((asl_object_private_t *)obj, position); | |
381 | } | |
382 | ||
383 | asl_object_t | |
384 | asl_search(asl_object_t data, asl_object_t query) | |
385 | { | |
386 | return (asl_object_t)asl_object_search((asl_object_private_t *)data, (asl_object_private_t *)query); | |
387 | } | |
388 | ||
389 | asl_object_t | |
390 | asl_match(asl_object_t data, asl_object_t qlist, size_t *last, size_t start, size_t count, uint32_t duration, int32_t direction) | |
391 | { | |
392 | return (asl_object_t)asl_object_match((asl_object_private_t *)data, (asl_object_private_t *)qlist, last, start, count, duration, direction); | |
393 | } | |
394 | ||
395 | void | |
396 | asl_free(asl_object_t obj) | |
397 | { | |
398 | asl_release(obj); | |
399 | } | |
400 | ||
401 | void | |
402 | aslresponse_free(asl_object_t obj) | |
403 | { | |
404 | asl_release(obj); | |
405 | } | |
406 | ||
407 | asl_object_t | |
408 | aslresponse_next(asl_object_t obj) | |
409 | { | |
410 | return (asl_object_t)asl_object_next((asl_object_private_t *)obj); | |
411 | } | |
412 | ||
413 | asl_object_t | |
414 | asl_list_from_string(const char *buf) | |
415 | { | |
416 | return (asl_object_t)asl_msg_list_from_string(buf); | |
417 | } | |
418 | ||
419 | char * | |
420 | asl_format(asl_object_t obj, const char *msg_fmt, const char *time_fmt, uint32_t text_encoding) | |
421 | { | |
422 | uint32_t len; | |
423 | uint32_t type = asl_get_type(obj); | |
424 | if (type != ASL_TYPE_MSG) return NULL; | |
425 | return asl_format_message((asl_msg_t *)obj, msg_fmt, time_fmt, text_encoding, &len); | |
426 | } |