2 * Copyright (c) 2007-2013 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 #include <asl_object.h>
25 #include <asl_private.h>
27 #include <asl_msg_list.h>
28 #include <asl_client.h>
29 #include <asl_store.h>
31 #include <dispatch/dispatch.h>
32 #include <libkern/OSAtomic.h>
34 static const asl_jump_table_t
*asl_jump
[ASL_TYPE_COUNT
];
35 static dispatch_once_t asl_object_once
;
38 _asl_object_init(void)
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();
49 #pragma mark asl_object
52 asl_object_set_key_val_op(asl_object_private_t
*obj
, const char *key
, const char *val
, uint16_t op
)
54 if (obj
== NULL
) return -1;
55 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return -1;
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
);
63 asl_object_unset_key(asl_object_private_t
*obj
, const char *key
)
65 if (obj
== NULL
) return;
66 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return;
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
);
74 asl_object_get_val_op_for_key(asl_object_private_t
*obj
, const char *key
, const char **val
, uint16_t *op
)
76 if (obj
== NULL
) return -1;
77 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return -1;
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
);
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
)
87 if (obj
== NULL
) return -1;
88 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return -1;
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
);
96 asl_object_count(asl_object_private_t
*obj
)
98 if (obj
== NULL
) return 0;
99 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return 0;
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
);
106 asl_object_private_t
*
107 asl_object_next(asl_object_private_t
*obj
)
109 if (obj
== NULL
) return NULL
;
110 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return NULL
;
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
);
117 asl_object_private_t
*
118 asl_object_prev(asl_object_private_t
*obj
)
120 if (obj
== NULL
) return NULL
;
121 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return NULL
;
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
);
128 asl_object_private_t
*
129 asl_object_get_object_at_index(asl_object_private_t
*obj
, size_t n
)
131 if (obj
== NULL
) return NULL
;
132 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return NULL
;
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
);
140 asl_object_set_iteration_index(asl_object_private_t
*obj
, size_t n
)
142 if (obj
== NULL
) return;
143 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return;
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
);
151 asl_object_remove_object_at_index(asl_object_private_t
*obj
, size_t n
)
153 if (obj
== NULL
) return;
154 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return;
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
);
162 asl_object_append(asl_object_private_t
*obj
, asl_object_private_t
*newobj
, void *addr
)
164 uint32_t type
= ASL_TYPE_CLIENT
;
166 if (obj
!= NULL
) type
= obj
->asl_type
;
167 if (type
>= ASL_TYPE_COUNT
) return;
169 dispatch_once(&asl_object_once
, ^{ _asl_object_init(); });
170 if (asl_jump
[type
]->append
== NULL
) return;
171 return asl_jump
[type
]->append(obj
, newobj
, addr
);
175 asl_object_prepend(asl_object_private_t
*obj
, asl_object_private_t
*newobj
)
177 if (obj
== NULL
) return;
178 if (obj
->asl_type
>= ASL_TYPE_COUNT
) return;
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
);
185 asl_object_private_t
*
186 asl_object_search(asl_object_private_t
*obj
, asl_object_private_t
*query
)
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
;
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
);
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
)
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
;
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
);
210 asl_retain(asl_object_t obj
)
212 asl_object_private_t
*oo
= (asl_object_private_t
*)obj
;
213 if (oo
== NULL
) return NULL
;
215 OSAtomicIncrement32Barrier(&(oo
->refcount
));
220 asl_release(asl_object_t obj
)
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;
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
);
232 asl_new(uint32_t type
)
234 if (type
>= ASL_TYPE_COUNT
) return NULL
;
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
);
243 #pragma mark utilities
246 asl_get_type(asl_object_t obj
)
248 asl_object_private_t
*oo
= (asl_object_private_t
*)obj
;
250 if (oo
== NULL
) return ASL_TYPE_UNDEF
;
251 return (int)oo
->asl_type
;
255 asl_get_value_for_key(asl_object_t obj
, const char *key
)
257 const char *val
= NULL
;
260 asl_object_get_val_op_for_key((asl_object_private_t
*)obj
, key
, &val
, &op
);
265 asl_set(asl_object_t obj
, const char *key
, const char *val
)
267 asl_object_private_t
*oo
= (asl_object_private_t
*)obj
;
270 if (oo
== NULL
) return -1;
271 if (oo
->asl_type
== ASL_TYPE_QUERY
) op
= (uint32_t)-1;
273 return asl_object_set_key_val_op(oo
, key
, val
, op
);
277 asl_unset_key(asl_object_t obj
, const char *key
)
279 asl_object_unset_key((asl_object_private_t
*)obj
, key
);
284 asl_set_key_val_op(asl_object_t obj
, const char *key
, const char *val
, uint16_t op
)
286 return asl_object_set_key_val_op((asl_object_private_t
*)obj
, key
, val
, op
);
290 asl_count(asl_object_t obj
)
292 return asl_object_count((asl_object_private_t
*)obj
);
296 asl_get_index(asl_object_t list
, size_t index
)
298 return (asl_object_t
)asl_object_get_object_at_index((asl_object_private_t
*)list
, index
);
302 asl_next(asl_object_t obj
)
304 return (asl_object_t
)asl_object_next((asl_object_private_t
*)obj
);
308 asl_prev(asl_object_t obj
)
310 return (asl_object_t
)asl_object_prev((asl_object_private_t
*)obj
);
314 asl_append(asl_object_t a
, asl_object_t b
)
316 asl_object_append((asl_object_private_t
*)a
, (asl_object_private_t
*)b
, __builtin_return_address(0));
320 asl_prepend(asl_object_t a
, asl_object_t b
)
322 asl_object_prepend((asl_object_private_t
*)a
, (asl_object_private_t
*)b
);
325 /* asl_send is implemented as asl_append */
327 asl_send(asl_object_t a
, asl_object_t b
)
329 asl_object_append((asl_object_private_t
*)a
, (asl_object_private_t
*)b
, __builtin_return_address(0));
334 asl_key(asl_object_t obj
, uint32_t n
)
336 const char *key
= NULL
;
339 if (asl_object_get_key_val_op_at_index((asl_object_private_t
*)obj
, sn
, &key
, NULL
, NULL
) != 0) return NULL
;
344 asl_get(asl_object_t obj
, const char *key
)
346 const char *val
= NULL
;
348 if (asl_object_get_val_op_for_key((asl_object_private_t
*)obj
, key
, &val
, NULL
) != 0) return NULL
;
353 asl_fetch_key_val_op(asl_object_t obj
, uint32_t n
, const char **key
, const char **val
, uint32_t *op
)
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
;
364 asl_set_query(asl_object_t obj
, const char *key
, const char *val
, uint32_t op
)
367 return asl_object_set_key_val_op((asl_object_private_t
*)obj
, key
, val
, op16
);
371 asl_unset(asl_object_t obj
, const char *key
)
373 asl_object_unset_key((asl_object_private_t
*)obj
, key
);
378 asl_reset_iteration(asl_object_t obj
, size_t position
)
380 asl_object_set_iteration_index((asl_object_private_t
*)obj
, position
);
384 asl_search(asl_object_t data
, asl_object_t query
)
386 return (asl_object_t
)asl_object_search((asl_object_private_t
*)data
, (asl_object_private_t
*)query
);
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
)
392 return (asl_object_t
)asl_object_match((asl_object_private_t
*)data
, (asl_object_private_t
*)qlist
, last
, start
, count
, duration
, direction
);
396 asl_free(asl_object_t obj
)
402 aslresponse_free(asl_object_t obj
)
408 aslresponse_next(asl_object_t obj
)
410 return (asl_object_t
)asl_object_next((asl_object_private_t
*)obj
);
414 asl_list_from_string(const char *buf
)
416 return (asl_object_t
)asl_msg_list_from_string(buf
);
420 asl_format(asl_object_t obj
, const char *msg_fmt
, const char *time_fmt
, uint32_t text_encoding
)
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
);