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
, void *addr
)
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