xref: /NextBSD/lib/libasl/asl_object.c (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
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 #ifdef __FreeBSD__
33 #include <atomic_compat.h>
34 #else
35 #include <libkern/OSAtomic.h>
36 #endif
37 
38 static const asl_jump_table_t *asl_jump[ASL_TYPE_COUNT];
39 static dispatch_once_t asl_object_once;
40 
41 static void
_asl_object_init(void)42 _asl_object_init(void)
43 {
44 	asl_jump[ASL_TYPE_MSG] = asl_msg_jump_table();
45 	asl_jump[ASL_TYPE_QUERY] = asl_msg_jump_table();
46 	asl_jump[ASL_TYPE_LIST] = asl_msg_list_jump_table();
47 	asl_jump[ASL_TYPE_FILE] = asl_file_jump_table();
48 	asl_jump[ASL_TYPE_STORE] = asl_store_jump_table();
49 	asl_jump[ASL_TYPE_CLIENT] = asl_client_jump_table();
50 }
51 
52 #pragma mark -
53 #pragma mark asl_object
54 
55 int
asl_object_set_key_val_op(asl_object_private_t * obj,const char * key,const char * val,uint16_t op)56 asl_object_set_key_val_op(asl_object_private_t *obj, const char *key, const char *val, uint16_t op)
57 {
58 	if (obj == NULL) return -1;
59 	if (obj->asl_type >= ASL_TYPE_COUNT) return -1;
60 
61 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
62 	if (asl_jump[obj->asl_type]->set_key_val_op == NULL) return -1;
63 	return asl_jump[obj->asl_type]->set_key_val_op(obj, key, val, op);
64 }
65 
66 void
asl_object_unset_key(asl_object_private_t * obj,const char * key)67 asl_object_unset_key(asl_object_private_t *obj, const char *key)
68 {
69 	if (obj == NULL) return;
70 	if (obj->asl_type >= ASL_TYPE_COUNT) return;
71 
72 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
73 	if (asl_jump[obj->asl_type]->unset_key == NULL) return;
74 	asl_jump[obj->asl_type]->unset_key(obj, key);
75 }
76 
77 int
asl_object_get_val_op_for_key(asl_object_private_t * obj,const char * key,const char ** val,uint16_t * op)78 asl_object_get_val_op_for_key(asl_object_private_t *obj, const char *key, const char **val, uint16_t *op)
79 {
80 	if (obj == NULL) return -1;
81 	if (obj->asl_type >= ASL_TYPE_COUNT) return -1;
82 
83 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
84 	if (asl_jump[obj->asl_type]->get_val_op_for_key == NULL) return -1;
85 	return asl_jump[obj->asl_type]->get_val_op_for_key(obj, key, val, op);
86 }
87 
88 int
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)89 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)
90 {
91 	if (obj == NULL) return -1;
92 	if (obj->asl_type >= ASL_TYPE_COUNT) return -1;
93 
94 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
95 	if (asl_jump[obj->asl_type]->get_key_val_op_at_index == NULL) return -1;
96 	return asl_jump[obj->asl_type]->get_key_val_op_at_index(obj, n, key, val, op);
97 }
98 
99 size_t
asl_object_count(asl_object_private_t * obj)100 asl_object_count(asl_object_private_t *obj)
101 {
102 	if (obj == NULL) return 0;
103 	if (obj->asl_type >= ASL_TYPE_COUNT) return 0;
104 
105 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
106 	if (asl_jump[obj->asl_type]->count == NULL) return 0;
107 	return asl_jump[obj->asl_type]->count(obj);
108 }
109 
110 asl_object_private_t *
asl_object_next(asl_object_private_t * obj)111 asl_object_next(asl_object_private_t *obj)
112 {
113 	if (obj == NULL) return NULL;
114 	if (obj->asl_type >= ASL_TYPE_COUNT) return NULL;
115 
116 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
117 	if (asl_jump[obj->asl_type]->next == NULL) return NULL;
118 	return asl_jump[obj->asl_type]->next(obj);
119 }
120 
121 asl_object_private_t *
asl_object_prev(asl_object_private_t * obj)122 asl_object_prev(asl_object_private_t *obj)
123 {
124 	if (obj == NULL) return NULL;
125 	if (obj->asl_type >= ASL_TYPE_COUNT) return NULL;
126 
127 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
128 	if (asl_jump[obj->asl_type]->prev == NULL) return NULL;
129 	return asl_jump[obj->asl_type]->prev(obj);
130 }
131 
132 asl_object_private_t *
asl_object_get_object_at_index(asl_object_private_t * obj,size_t n)133 asl_object_get_object_at_index(asl_object_private_t *obj, size_t n)
134 {
135 	if (obj == NULL) return NULL;
136 	if (obj->asl_type >= ASL_TYPE_COUNT) return NULL;
137 
138 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
139 	if (asl_jump[obj->asl_type]->get_object_at_index == NULL) return NULL;
140 	return asl_jump[obj->asl_type]->get_object_at_index(obj, n);
141 }
142 
143 void
asl_object_set_iteration_index(asl_object_private_t * obj,size_t n)144 asl_object_set_iteration_index(asl_object_private_t *obj, size_t n)
145 {
146 	if (obj == NULL) return;
147 	if (obj->asl_type >= ASL_TYPE_COUNT) return;
148 
149 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
150 	if (asl_jump[obj->asl_type]->set_iteration_index == NULL) return;
151 	return asl_jump[obj->asl_type]->set_iteration_index(obj, n);
152 }
153 
154 void
asl_object_remove_object_at_index(asl_object_private_t * obj,size_t n)155 asl_object_remove_object_at_index(asl_object_private_t *obj, size_t n)
156 {
157 	if (obj == NULL) return;
158 	if (obj->asl_type >= ASL_TYPE_COUNT) return;
159 
160 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
161 	if (asl_jump[obj->asl_type]->remove_object_at_index == NULL) return;
162 	return asl_jump[obj->asl_type]->remove_object_at_index(obj, n);
163 }
164 
165 void
asl_object_append(asl_object_private_t * obj,asl_object_private_t * newobj)166 asl_object_append(asl_object_private_t *obj, asl_object_private_t *newobj)
167 {
168 	int type = ASL_TYPE_CLIENT;
169 
170 	if (obj != NULL) type = obj->asl_type;
171 	if (type >= ASL_TYPE_COUNT) return;
172 
173 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
174 	if (asl_jump[type]->append == NULL) return;
175 	return asl_jump[type]->append(obj, newobj);
176 }
177 
178 void
asl_object_prepend(asl_object_private_t * obj,asl_object_private_t * newobj)179 asl_object_prepend(asl_object_private_t *obj, asl_object_private_t *newobj)
180 {
181 	if (obj == NULL) return;
182 	if (obj->asl_type >= ASL_TYPE_COUNT) return;
183 
184 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
185 	if (asl_jump[obj->asl_type]->prepend == NULL) return;
186 	return asl_jump[obj->asl_type]->prepend(obj, newobj);
187 }
188 
189 asl_object_private_t *
asl_object_search(asl_object_private_t * obj,asl_object_private_t * query)190 asl_object_search(asl_object_private_t *obj, asl_object_private_t *query)
191 {
192 	/* default to asl_client_search for obj == NULL */
193 	if (obj == NULL) return (asl_object_private_t *)asl_client_search(NULL, (asl_msg_t *)query);
194 	if (obj->asl_type >= ASL_TYPE_COUNT) return NULL;
195 
196 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
197 	if (asl_jump[obj->asl_type]->search == NULL) return NULL;
198 	return asl_jump[obj->asl_type]->search(obj, query);
199 }
200 
201 asl_object_private_t *
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)202 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)
203 {
204 	/* default to asl_client_match for obj == NULL */
205 	if (obj == NULL) return (asl_object_private_t *)asl_client_match(NULL, (asl_msg_list_t *)qlist, last, start, count, duration, dir);
206 	if (obj->asl_type >= ASL_TYPE_COUNT) return NULL;
207 
208 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
209 	if (asl_jump[obj->asl_type]->match == NULL) return NULL;
210 	return asl_jump[obj->asl_type]->match(obj, qlist, last, start, count, duration, dir);
211 }
212 
213 asl_object_t
asl_retain(asl_object_t obj)214 asl_retain(asl_object_t obj)
215 {
216 	asl_object_private_t *oo = (asl_object_private_t *)obj;
217 	if (oo == NULL) return NULL;
218 
219 	OSAtomicIncrement32Barrier(&(oo->refcount));
220 	return obj;
221 }
222 
223 void
asl_release(asl_object_t obj)224 asl_release(asl_object_t obj)
225 {
226 	asl_object_private_t *oo = (asl_object_private_t *)obj;
227 	if (oo == NULL) return;
228 	if (oo->asl_type >= ASL_TYPE_COUNT) return;
229 
230 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
231 	if (OSAtomicDecrement32Barrier(&(oo->refcount)) != 0) return;
232 	if (asl_jump[oo->asl_type]->dealloc != NULL) asl_jump[oo->asl_type]->dealloc(oo);
233 }
234 
235 asl_object_t
asl_new(uint32_t type)236 asl_new(uint32_t type)
237 {
238 	if (type >= ASL_TYPE_COUNT) return NULL;
239 
240 	dispatch_once(&asl_object_once, ^{ _asl_object_init(); });
241 	if (asl_jump[type]->alloc == NULL) return NULL;
242 	asl_object_t out = (asl_object_t)asl_jump[type]->alloc(type);
243 	return out;
244 }
245 
246 #pragma mark -
247 #pragma mark utilities
248 
249 uint32_t
asl_get_type(asl_object_t obj)250 asl_get_type(asl_object_t obj)
251 {
252 	asl_object_private_t *oo = (asl_object_private_t *)obj;
253 
254 	if (oo == NULL) return ASL_TYPE_UNDEF;
255 	return (int)oo->asl_type;
256 }
257 
258 const char *
asl_get_value_for_key(asl_object_t obj,const char * key)259 asl_get_value_for_key(asl_object_t obj, const char *key)
260 {
261 	const char *val = NULL;
262 	uint16_t op;
263 
264 	asl_object_get_val_op_for_key((asl_object_private_t *)obj, key, &val, &op);
265 	return val;
266 }
267 
268 int
asl_set(asl_object_t obj,const char * key,const char * val)269 asl_set(asl_object_t obj, const char *key, const char *val)
270 {
271 	asl_object_private_t *oo = (asl_object_private_t *)obj;
272 	uint16_t op = 0;
273 
274 	if (oo == NULL) return -1;
275 	if (oo->asl_type == ASL_TYPE_QUERY) op = (uint32_t)-1;
276 
277 	return asl_object_set_key_val_op(oo, key, val, op);
278 }
279 
280 int
asl_unset_key(asl_object_t obj,const char * key)281 asl_unset_key(asl_object_t obj, const char *key)
282 {
283 	asl_object_unset_key((asl_object_private_t *)obj, key);
284 	return 0;
285 }
286 
287 int
asl_set_key_val_op(asl_object_t obj,const char * key,const char * val,uint16_t op)288 asl_set_key_val_op(asl_object_t obj, const char *key, const char *val, uint16_t op)
289 {
290 	return asl_object_set_key_val_op((asl_object_private_t *)obj, key, val, op);
291 }
292 
293 size_t
asl_count(asl_object_t obj)294 asl_count(asl_object_t obj)
295 {
296 	return asl_object_count((asl_object_private_t *)obj);
297 }
298 
299 asl_object_t
asl_get_index(asl_object_t list,size_t index)300 asl_get_index(asl_object_t list, size_t index)
301 {
302 	return (asl_object_t)asl_object_get_object_at_index((asl_object_private_t *)list, index);
303 }
304 
305 asl_object_t
asl_next(asl_object_t obj)306 asl_next(asl_object_t obj)
307 {
308 	return (asl_object_t)asl_object_next((asl_object_private_t *)obj);
309 }
310 
311 asl_object_t
asl_prev(asl_object_t obj)312 asl_prev(asl_object_t obj)
313 {
314 	return (asl_object_t)asl_object_prev((asl_object_private_t *)obj);
315 }
316 
317 void
asl_append(asl_object_t a,asl_object_t b)318 asl_append(asl_object_t a, asl_object_t b)
319 {
320 	asl_object_append((asl_object_private_t *)a, (asl_object_private_t *)b);
321 }
322 
323 void
asl_prepend(asl_object_t a,asl_object_t b)324 asl_prepend(asl_object_t a, asl_object_t b)
325 {
326 	asl_object_prepend((asl_object_private_t *)a, (asl_object_private_t *)b);
327 }
328 
329 /* asl_send is implemented as asl_append */
330 int
asl_send(asl_object_t a,asl_object_t b)331 asl_send(asl_object_t a, asl_object_t b)
332 {
333 	asl_object_append((asl_object_private_t *)a, (asl_object_private_t *)b);
334 	return 0;
335 }
336 
337 const char *
asl_key(asl_object_t obj,uint32_t n)338 asl_key(asl_object_t obj, uint32_t n)
339 {
340 	const char *key = NULL;
341 	size_t sn = n;
342 
343 	if (asl_object_get_key_val_op_at_index((asl_object_private_t *)obj, sn, &key, NULL, NULL) != 0) return NULL;
344 	return key;
345 }
346 
347 const char *
asl_get(asl_object_t obj,const char * key)348 asl_get(asl_object_t obj, const char *key)
349 {
350 	const char *val = NULL;
351 
352 	if (asl_object_get_val_op_for_key((asl_object_private_t *)obj, key, &val, NULL) != 0) return NULL;
353 	return val;
354 }
355 
356 int
asl_fetch_key_val_op(asl_object_t obj,uint32_t n,const char ** key,const char ** val,uint32_t * op)357 asl_fetch_key_val_op(asl_object_t obj, uint32_t n, const char **key, const char **val, uint32_t *op)
358 {
359 	uint16_t op16;
360 	size_t sn = n;
361 	int status = asl_object_get_key_val_op_at_index((asl_object_private_t *)obj, sn, key, val, &op16);
362 	if (status != 0) return status;
363 	if (op != NULL) *op = op16;
364 	return 0;
365 }
366 
367 int
asl_set_query(asl_object_t obj,const char * key,const char * val,uint32_t op)368 asl_set_query(asl_object_t obj, const char *key, const char *val, uint32_t op)
369 {
370 	uint16_t op16 = op;
371 	return asl_object_set_key_val_op((asl_object_private_t *)obj, key, val, op16);
372 }
373 
374 int
asl_unset(asl_object_t obj,const char * key)375 asl_unset(asl_object_t obj, const char *key)
376 {
377 	asl_object_unset_key((asl_object_private_t *)obj, key);
378 	return 0;
379 }
380 
381 void
asl_reset_iteration(asl_object_t obj,size_t position)382 asl_reset_iteration(asl_object_t obj, size_t position)
383 {
384 	asl_object_set_iteration_index((asl_object_private_t *)obj, position);
385 }
386 
387 asl_object_t
asl_search(asl_object_t data,asl_object_t query)388 asl_search(asl_object_t data, asl_object_t query)
389 {
390 	return (asl_object_t)asl_object_search((asl_object_private_t *)data, (asl_object_private_t *)query);
391 }
392 
393 asl_object_t
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)394 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)
395 {
396 	return (asl_object_t)asl_object_match((asl_object_private_t *)data, (asl_object_private_t *)qlist, last, start, count, duration, direction);
397 }
398 
399 void
asl_free(asl_object_t obj)400 asl_free(asl_object_t obj)
401 {
402 	asl_release(obj);
403 }
404 
405 void
aslresponse_free(asl_object_t obj)406 aslresponse_free(asl_object_t obj)
407 {
408 	asl_release(obj);
409 }
410 
411 asl_object_t
aslresponse_next(asl_object_t obj)412 aslresponse_next(asl_object_t obj)
413 {
414 	return (asl_object_t)asl_object_next((asl_object_private_t *)obj);
415 }
416 
417 asl_object_t
asl_list_from_string(const char * buf)418 asl_list_from_string(const char *buf)
419 {
420 	return (asl_object_t)asl_msg_list_from_string(buf);
421 }
422 
423 char *
asl_format(asl_object_t obj,const char * msg_fmt,const char * time_fmt,uint32_t text_encoding)424 asl_format(asl_object_t obj, const char *msg_fmt, const char *time_fmt, uint32_t text_encoding)
425 {
426 	uint32_t len;
427 	uint32_t type = asl_get_type(obj);
428 	if (type != ASL_TYPE_MSG) return NULL;
429 	return asl_format_message((asl_msg_t *)obj, msg_fmt, time_fmt, text_encoding, &len);
430 }
431