2  * Copyright (c) 2012-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@ 
  32 #include <asl_msg_list.h> 
  35 asl_msg_list_new(void) 
  37         asl_msg_list_t 
*out 
= (asl_msg_list_t 
*)calloc(1, sizeof(asl_msg_list_t
)); 
  38         if (out 
== NULL
) return NULL
; 
  40         out
->asl_type 
= ASL_TYPE_LIST
; 
  47 asl_msg_list_new_count(uint32_t n
) 
  49         asl_msg_list_t 
*out 
= (asl_msg_list_t 
*)calloc(1, sizeof(asl_msg_list_t
)); 
  50         if (out 
== NULL
) return NULL
; 
  52         out
->asl_type 
= ASL_TYPE_LIST
; 
  56         out
->msg 
= (asl_msg_t 
**)reallocf(out
->msg
, out
->count 
* sizeof(asl_msg_t 
*)); 
  67 asl_msg_list_retain(asl_msg_list_t 
*list
) 
  69         if (list 
== NULL
) return NULL
; 
  70         asl_retain((asl_object_t
)list
); 
  75 asl_msg_list_release(asl_msg_list_t 
*list
) 
  77         if (list 
== NULL
) return; 
  78         asl_release((asl_object_t
)list
); 
  82 asl_msg_list_to_string(asl_msg_list_t 
*list
, uint32_t *len
) 
  89         if (list 
== NULL
) return NULL
; 
  90         if (list
->count 
== 0) return NULL
; 
  91         if (list
->msg 
== NULL
) return NULL
; 
  93         str 
= asl_string_new(ASL_ENCODE_ASL
); 
  94         if (str 
== NULL
) return NULL
; 
  96         snprintf(tmp
, sizeof(tmp
), "%u", list
->count
); 
  97         asl_string_append(str
, tmp
); 
  98         asl_string_append_char_no_encoding(str
, '\n'); 
 100         for (i 
= 0; i 
< list
->count
; i
++) 
 102                 asl_string_append_asl_msg(str
, list
->msg
[i
]); 
 103                 asl_string_append_char_no_encoding(str
, '\n'); 
 106         *len 
= asl_string_length(str
); 
 107         out 
= asl_string_release_return_bytes(str
); 
 112 asl_msg_list_to_asl_string(asl_msg_list_t 
*list
, uint32_t encoding
) 
 118         if (list 
== NULL
) return NULL
; 
 119         if (list
->count 
== 0) return NULL
; 
 120         if (list
->msg 
== NULL
) return NULL
; 
 122         str 
= asl_string_new(encoding
); 
 123         if (str 
== NULL
) return NULL
; 
 125         snprintf(tmp
, sizeof(tmp
), "%u", list
->count
); 
 126         asl_string_append(str
, tmp
); 
 127         asl_string_append_char_no_encoding(str
, '\n'); 
 129         for (i 
= 0; i 
< list
->count
; i
++) 
 131                 asl_string_append_asl_msg(str
, list
->msg
[i
]); 
 132                 asl_string_append_char_no_encoding(str
, '\n'); 
 139 asl_msg_list_from_string(const char *buf
) 
 146         if (buf 
== NULL
) return NULL
; 
 150         if (n 
== 0) return NULL
; 
 152         out 
= asl_msg_list_new(); 
 153         if (out 
== NULL
) return NULL
; 
 155         for (i 
= 0; i 
< n
; i
++) 
 160                         asl_msg_list_release(out
); 
 166                 m 
= asl_msg_from_string(p
); 
 169                         asl_msg_list_release(out
); 
 173                 asl_msg_list_append(out
, m
); 
 181 asl_msg_list_insert(asl_msg_list_t 
*list
, uint32_t x
, void *obj
) 
 184         asl_object_private_t 
*oo 
= (asl_object_private_t 
*)obj
; 
 186         if (list 
== NULL
) return; 
 187         if (obj 
== NULL
) return; 
 188         if (list
->count 
== UINT32_MAX
) return; 
 190         if (x 
>= list
->count
) x 
= list
->count
; 
 192         uint32_t type 
= asl_get_type((asl_object_t
)oo
); 
 195         if ((type 
== ASL_TYPE_MSG
) || (type 
== ASL_TYPE_QUERY
)) count 
= 1; 
 196         else count 
= asl_object_count(oo
); 
 198         if (count 
== 0) return; 
 200         uint64_t check 
= list
->count
; 
 202         if (check 
> UINT32_MAX
) return; 
 204         list
->msg 
= (asl_msg_t 
**)reallocf(list
->msg
, (list
->count 
+ count
) * sizeof(asl_msg_t 
*)); 
 205         if (list
->msg 
== NULL
) 
 212         for (i 
= list
->count
, j 
= i 
- 1; i 
> x
; i
--, j
--) list
->msg
[i
] = list
->msg
[j
]; 
 214         asl_object_set_iteration_index(oo
, 0); 
 216         if ((type 
== ASL_TYPE_MSG
) || (type 
== ASL_TYPE_QUERY
)) 
 218                 list
->msg
[x
] = (asl_msg_t 
*)asl_retain((asl_object_t
)oo
); 
 222                 for (i 
= x
, j 
= 0; j 
< count
; i
++, j
++) list
->msg
[i
] = (asl_msg_t 
*)asl_object_next(oo
); 
 225         asl_object_set_iteration_index(oo
, 0); 
 227         list
->count 
+= count
; 
 231 asl_msg_list_append(asl_msg_list_t 
*list
, void *obj
) 
 233         asl_msg_list_insert(list
, UINT32_MAX
, obj
); 
 237 asl_msg_list_prepend(asl_msg_list_t 
*list
, void *obj
) 
 239         asl_msg_list_insert(list
, 0, obj
); 
 243 asl_msg_list_count(asl_msg_list_t 
*list
) 
 245         if (list 
== NULL
) return 0; 
 250 asl_msg_list_get_index(asl_msg_list_t 
*list
, size_t index
) 
 254         if (list 
== NULL
) return NULL
; 
 255         if (index 
>= list
->count
) return NULL
; 
 256         if (list
->msg 
== NULL
) 
 263         out 
= list
->msg
[index
]; 
 268 asl_msg_list_remove_index(asl_msg_list_t 
*list
, size_t index
) 
 272         if (list 
== NULL
) return; 
 273         if (index 
>= list
->count
) return; 
 274         if (list
->msg 
== NULL
) 
 281         asl_msg_release(list
->msg
[index
]); 
 283         for (i 
= index 
+ 1, j 
= index
; i 
< list
->count
; i
++) list
->msg
[j
] = list
->msg
[i
]; 
 286         list
->msg 
= (asl_msg_t 
**)reallocf(list
->msg
, list
->count 
* sizeof(asl_msg_t 
*)); 
 287         if (list
->msg 
== NULL
) 
 295 asl_msg_list_next(asl_msg_list_t 
*list
) 
 299         if (list 
== NULL
) return NULL
; 
 300         if (list
->curr 
>= list
->count
) return NULL
; 
 301         if (list
->msg 
== NULL
) 
 308         out 
= list
->msg
[list
->curr
]; 
 314 asl_msg_list_prev(asl_msg_list_t 
*list
) 
 318         if (list 
== NULL
) return NULL
; 
 319         if (list
->curr 
== 0) return NULL
; 
 320         if (list
->msg 
== NULL
) 
 327         if (list
->curr 
> list
->count
) list
->curr 
= list
->count
; 
 330         out 
= list
->msg
[list
->curr
]; 
 335 asl_msg_list_reset_iteration(asl_msg_list_t 
*list
, size_t position
) 
 337         if (list 
== NULL
) return; 
 339         if (position 
> list
->count
) position 
= SIZE_MAX
; 
 340         list
->curr 
= position
; 
 344 asl_msg_list_search(asl_msg_list_t 
*list
, asl_msg_t 
*query
) 
 347         asl_msg_list_t 
*out 
= NULL
; 
 349         if (list 
== NULL
) return NULL
; 
 351         if (list
->msg 
== NULL
) 
 358         for (i 
= 0; i 
< list
->count
; i
++) 
 361                 if (query 
== NULL
) match 
= 1; 
 362                 else match 
= asl_msg_cmp(query
, list
->msg
[i
]); 
 366                         if (out 
== NULL
) out 
= asl_msg_list_new(); 
 367                         if (out 
== NULL
) return NULL
; 
 368                         asl_msg_list_append(out
, list
->msg
[i
]); 
 376 asl_msg_list_match(asl_msg_list_t 
*list
, asl_msg_list_t 
*qlist
, size_t *last
, size_t start
, size_t count
, uint32_t duration
, int32_t direction
) 
 378         uint32_t i
, end
, n 
= 0; 
 379         struct timeval now
, finish
; 
 380         asl_msg_list_t 
*out 
= NULL
; 
 382         if (list 
== NULL
) return NULL
; 
 383         if (list
->msg 
== NULL
) 
 390         /* start the timer if a timeout was specified */ 
 391         memset(&finish
, 0, sizeof(struct timeval
)); 
 394                 if (gettimeofday(&finish
, NULL
) == 0) 
 396                         finish
.tv_sec 
+= (duration 
/ USEC_PER_SEC
); 
 397                         finish
.tv_usec 
+= (duration 
% USEC_PER_SEC
); 
 398                         if (finish
.tv_usec 
> USEC_PER_SEC
) 
 400                                 finish
.tv_usec 
-= USEC_PER_SEC
; 
 406                         /* shouldn't happen, but if gettimeofday failed we just run without a timeout */ 
 407                         memset(&finish
, 0, sizeof(struct timeval
)); 
 411         end 
= list
->count 
- 1; 
 414                 if (start 
>= list
->count
) 
 416                         if (last 
!= NULL
) *last 
= list
->count
; 
 424                 if (start 
>= list
->count
) start 
= list
->count 
- 1; 
 434                 if (qlist 
== NULL
) match 
= 1; 
 435                 else match 
= asl_msg_cmp_list(list
->msg
[i
], qlist
); 
 437                 if (last 
!= NULL
) *last 
= i
; 
 441                         if (out 
== NULL
) out 
= asl_msg_list_new(); 
 442                         if (out 
== NULL
) return NULL
; 
 444                         asl_msg_list_append(out
, list
->msg
[i
]); 
 448                 if (n 
>= count
) return n
; 
 450                 /* check the timer */ 
 451                 if ((finish
.tv_sec 
!= 0) && (gettimeofday(&now
, NULL
) == 0)) 
 453                         if ((now
.tv_sec 
> finish
.tv_sec
) || ((now
.tv_sec 
== finish
.tv_sec
) && (now
.tv_usec 
> finish
.tv_usec
))) return n
; 
 463 #pragma mark asl_object support 
 465 static asl_object_private_t 
* 
 466 _jump_alloc(uint32_t type
) 
 468         return (asl_object_private_t 
*)asl_msg_list_new(); 
 472 _jump_dealloc(asl_object_private_t 
*obj
) 
 474         asl_msg_list_t 
*list 
= (asl_msg_list_t 
*)obj
; 
 476         if (list 
== NULL
) return; 
 477         if (list
->msg 
!= NULL
) 
 480                 for (i 
= 0; i 
< list
->count
; i
++) asl_msg_release(list
->msg
[i
]); 
 488 _jump_count(asl_object_private_t 
*obj
) 
 490         return asl_msg_list_count((asl_msg_list_t 
*)obj
); 
 493 static asl_object_private_t 
* 
 494 _jump_next(asl_object_private_t 
*obj
) 
 496         return (asl_object_private_t 
*)asl_msg_list_next((asl_msg_list_t 
*)obj
); 
 499 static asl_object_private_t 
* 
 500 _jump_prev(asl_object_private_t 
*obj
) 
 502         return (asl_object_private_t 
*)asl_msg_list_prev((asl_msg_list_t 
*)obj
); 
 505 static asl_object_private_t 
* 
 506 _jump_get_object_at_index(asl_object_private_t 
*obj
, size_t n
) 
 508         return (asl_object_private_t 
*)asl_msg_list_get_index((asl_msg_list_t 
*)obj
, n
); 
 512 _jump_set_iteration_index(asl_object_private_t 
*obj
, size_t n
) 
 514         asl_msg_list_reset_iteration((asl_msg_list_t 
*)obj
, n
); 
 518 _jump_remove_object_at_index(asl_object_private_t 
*obj
, size_t n
) 
 520         asl_msg_list_remove_index((asl_msg_list_t 
*)obj
, n
); 
 524 _jump_append(asl_object_private_t 
*obj
, asl_object_private_t 
*newobj
) 
 526         int type 
= asl_get_type((asl_object_t
)newobj
); 
 527         if ((type 
!= ASL_TYPE_QUERY
) && (type 
!= ASL_TYPE_MSG
)) return; 
 529         asl_msg_list_append((asl_msg_list_t 
*)obj
, newobj
); 
 533 _jump_prepend(asl_object_private_t 
*obj
, asl_object_private_t 
*newobj
) 
 535         int type 
= asl_get_type((asl_object_t
)newobj
); 
 536         if ((type 
!= ASL_TYPE_QUERY
) && (type 
!= ASL_TYPE_MSG
)) return; 
 538         asl_msg_list_prepend((asl_msg_list_t 
*)obj
, newobj
); 
 541 static asl_object_private_t 
* 
 542 _jump_search(asl_object_private_t 
*obj
, asl_object_private_t 
*query
) 
 544         int type 
= asl_get_type((asl_object_t
)query
); 
 546         if ((query 
!= NULL
) && (type 
!= ASL_TYPE_QUERY
) && (type 
!= ASL_TYPE_MSG
)) return NULL
; 
 548         asl_msg_list_t 
*out 
= asl_msg_list_search((asl_msg_list_t 
*)obj
, (asl_msg_t 
*)query
); 
 549         if (out 
== NULL
) return NULL
; 
 550         return (asl_object_private_t 
*)out
; 
 553 static asl_object_private_t 
* 
 554 _jump_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
) 
 556         int type 
= asl_get_type((asl_object_t
)qlist
); 
 558         if ((qlist 
!= NULL
) && (type 
!= ASL_TYPE_LIST
)) return NULL
; 
 560         return (asl_object_private_t 
*)asl_msg_list_match((asl_msg_list_t 
*)obj
, (asl_msg_list_t 
*)qlist
, last
, start
, count
, duration
, dir
); 
 563 __private_extern__ 
const asl_jump_table_t 
* 
 564 asl_msg_list_jump_table() 
 566         static const asl_jump_table_t jump 
= 
 568                 .alloc 
= &_jump_alloc
, 
 569                 .dealloc 
= &_jump_dealloc
, 
 570                 .set_key_val_op 
= NULL
, 
 572                 .get_val_op_for_key 
= NULL
, 
 573                 .get_key_val_op_at_index 
= NULL
, 
 574                 .count 
= &_jump_count
, 
 577                 .get_object_at_index 
= &_jump_get_object_at_index
, 
 578                 .set_iteration_index 
= &_jump_set_iteration_index
, 
 579                 .remove_object_at_index 
= &_jump_remove_object_at_index
, 
 580                 .append 
= &_jump_append
, 
 581                 .prepend 
= &_jump_prepend
, 
 582                 .search 
= &_jump_search
, 
 583                 .match 
= &_jump_match