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 34static const asl_jump_table_t *asl_jump[ASL_TYPE_COUNT]; 35static dispatch_once_t asl_object_once; 36 37static 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 51int 52asl_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 62void 63asl_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 73int 74asl_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 84int 85asl_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 95size_t 96asl_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 106asl_object_private_t * 107asl_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 117asl_object_private_t * 118asl_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 128asl_object_private_t * 129asl_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 139void 140asl_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 150void 151asl_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 161void 162asl_object_append(asl_object_private_t *obj, asl_object_private_t *newobj) 163{ 164 int type = ASL_TYPE_CLIENT; 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; 171 return asl_jump[type]->append(obj, newobj); 172} 173 174void 175asl_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 185asl_object_private_t * 186asl_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 197asl_object_private_t * 198asl_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 209asl_object_t 210asl_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 219void 220asl_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 231asl_object_t 232asl_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 245uint32_t 246asl_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 254const char * 255asl_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 264int 265asl_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 276int 277asl_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 283int 284asl_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 289size_t 290asl_count(asl_object_t obj) 291{ 292 return asl_object_count((asl_object_private_t *)obj); 293} 294 295asl_object_t 296asl_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 301asl_object_t 302asl_next(asl_object_t obj) 303{ 304 return (asl_object_t)asl_object_next((asl_object_private_t *)obj); 305} 306 307asl_object_t 308asl_prev(asl_object_t obj) 309{ 310 return (asl_object_t)asl_object_prev((asl_object_private_t *)obj); 311} 312 313void 314asl_append(asl_object_t a, asl_object_t b) 315{ 316 asl_object_append((asl_object_private_t *)a, (asl_object_private_t *)b); 317} 318 319void 320asl_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 */ 326int 327asl_send(asl_object_t a, asl_object_t b) 328{ 329 asl_object_append((asl_object_private_t *)a, (asl_object_private_t *)b); 330 return 0; 331} 332 333const char * 334asl_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 343const char * 344asl_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 352int 353asl_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 363int 364asl_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 370int 371asl_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 377void 378asl_reset_iteration(asl_object_t obj, size_t position) 379{ 380 asl_object_set_iteration_index((asl_object_private_t *)obj, position); 381} 382 383asl_object_t 384asl_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 389asl_object_t 390asl_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 395void 396asl_free(asl_object_t obj) 397{ 398 asl_release(obj); 399} 400 401void 402aslresponse_free(asl_object_t obj) 403{ 404 asl_release(obj); 405} 406 407asl_object_t 408aslresponse_next(asl_object_t obj) 409{ 410 return (asl_object_t)asl_object_next((asl_object_private_t *)obj); 411} 412 413asl_object_t 414asl_list_from_string(const char *buf) 415{ 416 return (asl_object_t)asl_msg_list_from_string(buf); 417} 418 419char * 420asl_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} 427