5 // Copyright (c) 2020 Apple Inc. All rights reserved.
8 #pragma mark - Includes
9 #include "mDNSEmbeddedAPI.h"
10 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
13 #pragma mark - list_init
15 list_init(list_t
* const _Nonnull list_to_init
, const mDNSu32 new_data_size
) {
16 // use dummy head and tail to handle the corner case such as adding node to empty list
17 list_to_init
->head_ptr
= &(list_to_init
->head
);
18 list_to_init
->tail_ptr
= &(list_to_init
->tail
);
19 list_to_init
->head_ptr
->next
= list_to_init
->tail_ptr
;
20 list_to_init
->tail_ptr
->prev
= list_to_init
->head_ptr
;
21 // data size is used to prevent from adding different structures into list
22 list_to_init
->data_size
= new_data_size
;
25 #pragma mark - list_append_uinitialized
27 list_append_uinitialized(list_t
* const _Nonnull list_ptr
, const mDNSu32 new_data_size
, void * _Nullable
* _Nonnull out_data_ptr
) {
28 mStatus error
= mStatus_NoError
;
29 list_node_t
* node_ptr
= mDNSNULL
;
30 list_node_t
* real_tail
= mDNSNULL
;
32 require_action(list_ptr
->data_size
== new_data_size
, exit
, error
= mStatus_BadParamErr
);
34 node_ptr
= malloc(offsetof(list_node_t
, data
) + new_data_size
);
35 require_action(node_ptr
!= mDNSNULL
, exit
, error
= mStatus_NoMemoryErr
);
37 *out_data_ptr
= &node_ptr
->data
;
39 real_tail
= list_ptr
->tail_ptr
->prev
;
40 real_tail
->next
= node_ptr
;
41 node_ptr
->prev
= real_tail
;
42 node_ptr
->next
= list_ptr
->tail_ptr
;
43 list_ptr
->tail_ptr
->prev
= node_ptr
;
46 if (error
!= mStatus_NoError
&& node_ptr
!= mDNSNULL
) free(node_ptr
);
50 #pragma mark - list_prepend_uinitialized
52 list_prepend_uinitialized(list_t
* const _Nonnull list_ptr
, const mDNSu32 new_data_size
, void * _Nullable
* _Nonnull out_data_ptr
) {
53 mStatus error
= mStatus_NoError
;
54 list_node_t
* node_ptr
= mDNSNULL
;
55 list_node_t
* real_head
= mDNSNULL
;
57 require_action(list_ptr
->data_size
== new_data_size
, exit
, error
= mStatus_BadParamErr
);
59 node_ptr
= malloc(offsetof(list_node_t
, data
) + new_data_size
);
60 require_action(node_ptr
!= mDNSNULL
, exit
, error
= mStatus_NoMemoryErr
);
62 *out_data_ptr
= &node_ptr
->data
;
64 real_head
= list_ptr
->head_ptr
->next
;
65 real_head
->prev
= node_ptr
;
66 node_ptr
->next
= real_head
;
67 node_ptr
->prev
= list_ptr
->head_ptr
;
68 list_ptr
->head_ptr
->next
= node_ptr
;
71 if (error
!= mDNSNULL
&& node_ptr
!= mDNSNULL
) free(node_ptr
);
75 #pragma mark - list_append_node
77 list_append_node(list_t
* const _Nonnull list_ptr
, list_node_t
* const _Nonnull node_ptr
) {
78 node_ptr
->prev
= list_ptr
->head_ptr
;
79 node_ptr
->next
= list_ptr
->head_ptr
->next
;
80 list_ptr
->head_ptr
->next
->prev
= node_ptr
;
81 list_ptr
->head_ptr
->next
= node_ptr
;
84 #pragma mark - list_prepend_node
86 list_prepend_node(list_t
*const _Nonnull list_ptr
, list_node_t
* const _Nonnull node_ptr
) {
87 node_ptr
->prev
= list_ptr
->tail_ptr
->prev
;
88 node_ptr
->next
= list_ptr
->tail_ptr
;
89 list_ptr
->tail_ptr
->prev
->next
= node_ptr
;
90 list_ptr
->tail_ptr
->prev
= node_ptr
;
93 #pragma mark - list_append_node_at_node
95 list_append_node_at_node(list_node_t
* const _Nonnull original_node
, list_node_t
* const _Nonnull added_node
) {
96 list_node_t
* const original_next
= original_node
->next
;
98 added_node
->prev
= original_node
;
99 added_node
->next
= original_next
;
100 original_node
->next
= added_node
;
101 original_next
->prev
= added_node
;
104 #pragma mark - list_prepend_node_at_node
106 list_prepend_node_at_node(list_node_t
* const _Nonnull original_node
, list_node_t
* const _Nonnull added_node
) {
107 list_node_t
* const original_prev
= original_node
->prev
;
109 added_node
->prev
= original_prev
;
110 added_node
->next
= original_node
;
111 original_prev
->next
= added_node
;
112 original_node
->prev
= added_node
;
115 #pragma mark - list_concatenate
117 list_concatenate(list_t
* const _Nonnull dst_list
, list_t
* const _Nonnull src_list
) {
118 list_node_t
*dst_last_node
= dst_list
->tail_ptr
->prev
;
119 list_node_t
*src_first_node
= src_list
->head_ptr
->next
;
120 list_node_t
*src_last_node
= src_list
->tail_ptr
->prev
;
122 if (list_empty(src_list
)) {
126 src_list
->head_ptr
->next
= src_list
->tail_ptr
;
127 src_list
->tail_ptr
->prev
= src_list
->head_ptr
;
129 dst_last_node
->next
= src_first_node
;
130 src_first_node
->prev
= dst_last_node
;
131 src_last_node
->next
= dst_list
->tail_ptr
;
132 dst_list
->tail_ptr
->prev
= src_last_node
;
135 #pragma mark - node_list_sort
137 node_list_sort(list_node_t
* _Nullable
* const _Nonnull in_out_list_ptr
, list_sort_comparator_t comparator
);
139 #pragma mark - node_list_tail
140 mDNSlocal list_node_t
*
141 node_list_tail(list_node_t
* _Nonnull list_ptr
);
143 #pragma mark - list_sort
145 list_sort(list_t
* const _Nonnull list_ptr
, list_sort_comparator_t comparator
) {
146 list_node_t
*real_head
= list_ptr
->head_ptr
->next
;
148 if (list_empty(list_ptr
)) {
152 list_ptr
->tail_ptr
->prev
->next
= mDNSNULL
;
153 list_ptr
->head_ptr
->next
= list_ptr
->tail_ptr
;
154 list_ptr
->tail_ptr
->prev
= list_ptr
->head_ptr
;
156 node_list_sort(&real_head
, comparator
);
158 list_ptr
->head_ptr
->next
= real_head
;
159 list_ptr
->tail_ptr
->prev
= node_list_tail(real_head
);
160 real_head
->prev
= list_ptr
->head_ptr
;
161 list_ptr
->tail_ptr
->prev
->next
= list_ptr
->tail_ptr
;
164 #pragma mark - front_back_split
166 front_back_split(list_node_t
* const _Nonnull list_ptr
, list_node_t
**out_front
, list_node_t
**out_back
);
168 #pragma mark - sorted_merge
169 mDNSlocal list_node_t
*
170 sorted_merge(list_node_t
* _Nullable left
, list_node_t
* _Nullable right
, list_sort_comparator_t comparator
);
172 #pragma mark - node_list_sort
174 node_list_sort(list_node_t
* _Nullable
* const _Nonnull in_out_list_ptr
, list_sort_comparator_t comparator
) {
175 list_node_t
*list_ptr
= *in_out_list_ptr
;
176 list_node_t
*front_half
;
177 list_node_t
*back_half
;
179 if (list_ptr
== mDNSNULL
|| list_ptr
->next
== mDNSNULL
)
182 front_back_split(list_ptr
, &front_half
, &back_half
);
184 node_list_sort(&front_half
, comparator
);
185 node_list_sort(&back_half
, comparator
);
187 *in_out_list_ptr
= sorted_merge(front_half
, back_half
, comparator
);
190 #pragma mark - front_back_split
193 list_node_t
* const _Nonnull list_ptr
,
194 list_node_t
* _Nullable
* _Nonnull out_front
,
195 list_node_t
* _Nullable
* _Nonnull out_back
) {
197 list_node_t
*fast
= list_ptr
->next
;
198 list_node_t
*slow
= list_ptr
;
200 while (fast
!= mDNSNULL
) {
202 if (fast
!= mDNSNULL
) {
208 *out_front
= list_ptr
;
209 *out_back
= slow
->next
;
210 slow
->next
= mDNSNULL
;
213 #pragma mark - sorted_merge
214 mDNSlocal list_node_t
*
215 sorted_merge(list_node_t
* _Nullable left
, list_node_t
* _Nullable right
, list_sort_comparator_t comparator
) {
216 list_node_t
*sorted_list
;
220 if (left
== mDNSNULL
) {
222 } else if (right
== mDNSNULL
) {
226 cmp_result
= comparator(left
, right
);
227 if (cmp_result
<= 0) {
238 while (left
!= mDNSNULL
&& right
!= mDNSNULL
) {
239 cmp_result
= comparator(left
, right
);
240 if (cmp_result
<= 0) {
252 if (left
!= mDNSNULL
) {
261 #pragma mark - node_list_tail
262 mDNSlocal list_node_t
*
263 node_list_tail(list_node_t
* _Nonnull list_ptr
) {
264 while (list_ptr
->next
!= mDNSNULL
) {
265 list_ptr
= list_ptr
->next
;
271 #pragma mark - list_node_detach
273 list_node_detach(list_node_t
* const _Nonnull node
) {
274 list_node_t
*prev
= node
->prev
;
275 list_node_t
*next
= node
->next
;
280 #pragma mark - list_node_delete
282 list_node_delete(list_node_t
* const _Nonnull node_ptr
) {
286 prev
= node_ptr
->prev
;
287 next
= node_ptr
->next
;
295 #pragma mark - list_node_delete_all
297 list_node_delete_all(list_t
* const _Nonnull list_ptr
) {
298 list_node_t
*next_node
;
299 for (list_node_t
* node
= list_get_first(list_ptr
); !list_has_ended(list_ptr
, node
); node
= next_node
) {
300 next_node
= list_next(node
);
301 list_node_delete(node
);
305 #pragma mark - list_delete_node_with_data_ptr
307 list_delete_node_with_data_ptr(list_t
* const _Nonnull list_ptr
, void * const _Nonnull data
) {
308 mStatus error
= mStatus_NoSuchKey
;
310 for (list_node_t
*ptr
= list_get_first(list_ptr
); !list_has_ended(list_ptr
, ptr
); ptr
= list_next(ptr
)) {
311 if (data
== &ptr
->data
) {
312 list_node_delete(ptr
);
313 error
= mStatus_NoError
;
321 #pragma mark - list_empty
323 list_empty(const list_t
* const _Nonnull list_ptr
) {
324 return list_ptr
->head_ptr
->next
== list_ptr
->tail_ptr
;
327 #pragma mark - list_count_node
329 list_count_node(const list_t
*const _Nonnull list_ptr
) {
332 if (list_empty(list_ptr
)) {
336 for (list_node_t
*ptr
= list_get_first(list_ptr
); !list_has_ended(list_ptr
, ptr
); ptr
= list_next(ptr
)) {
343 #pragma mark - list_get_first
344 mDNSexport list_node_t
* _Nullable
345 list_get_first(const list_t
* const _Nonnull list_ptr
) {
346 if (list_empty(list_ptr
)) {
350 return list_ptr
->head_ptr
->next
;
353 #pragma mark - list_get_last
354 mDNSexport list_node_t
* _Nullable
355 list_get_last(const list_t
* const _Nonnull list_ptr
) {
356 if (list_empty(list_ptr
)) {
360 return list_ptr
->tail_ptr
->prev
;
363 #pragma mark - list_next
364 mDNSexport list_node_t
* _Nonnull
365 list_next(const list_node_t
* const _Nonnull node_ptr
) {
366 return node_ptr
->next
;
369 #pragma mark - list_has_ended
371 list_has_ended(const list_t
* const _Nonnull list_ptr
, const list_node_t
* const _Nullable node_ptr
) {
372 if (node_ptr
== mDNSNULL
) {
375 return node_ptr
== list_ptr
->tail_ptr
;
378 #pragma mark - list_uninit
380 list_uninit(list_t
* const _Nonnull list_ptr
) {
381 list_node_delete_all(list_ptr
);
383 list_ptr
->data_size
= 0;
384 list_ptr
->head_ptr
->next
= mDNSNULL
;
385 list_ptr
->tail_ptr
->prev
= mDNSNULL
;
386 list_ptr
->head_ptr
= mDNSNULL
;
387 list_ptr
->tail_ptr
= mDNSNULL
;
390 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)