2 * Copyright (c) 2020 Apple Inc. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * https://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "mdns_helpers.h"
19 #include "mdns_objects.h"
21 #include <CoreUtils/CoreUtils.h>
23 //======================================================================================================================
24 // MARK: - Set Kind Definition
26 typedef struct _subset_s
* _subset_t
;
29 struct mdns_object_s base
; // Object base.
30 _subset_t list
; // Subset list.
33 MDNS_OBJECT_SUBKIND_DEFINE(set
);
35 //======================================================================================================================
36 // MARK: - Internal Data Structures
38 typedef struct _item_s
* _item_t
;
40 _item_t next
; // Next item in list.
41 mdns_object_t object
; // Object.
45 _subset_t next
; // Next subset in list.
46 uintptr_t ident
; // Subset ID.
47 _item_t list
; // Querier list.
48 size_t count
; // Item count.
51 //======================================================================================================================
52 // MARK: - Internal Helper Function Prototypes
55 _subset_create(uintptr_t subset_id
);
58 _subset_free(_subset_t subset
);
59 #define _subset_forget(X) ForgetCustom(X, _subset_free)
62 _item_create(mdns_object_t object
);
65 _item_free(_item_t item
);
66 #define _item_forget(X) ForgetCustom(X, _item_free)
68 //======================================================================================================================
69 // MARK: - Set Public Methods
74 return _mdns_set_alloc();
77 //======================================================================================================================
80 mdns_set_add(const mdns_set_t me
, const uintptr_t subset_id
, const mdns_object_t object
)
82 _subset_t
*subset_ptr
;
84 for (subset_ptr
= &me
->list
; (subset
= *subset_ptr
) != NULL
; subset_ptr
= &subset
->next
) {
85 if (subset
->ident
== subset_id
) {
90 _subset_t new_subset
= NULL
;
92 new_subset
= _subset_create(subset_id
);
93 require_action_quiet(new_subset
, exit
, err
= kNoMemoryErr
);
98 for (item_ptr
= &subset
->list
; (item
= *item_ptr
) != NULL
; item_ptr
= &item
->next
) {
99 if (item
->object
== object
) {
103 require_action_quiet(!item
, exit
, err
= kNoErr
);
105 item
= _item_create(object
);
106 require_action_quiet(item
, exit
, err
= kNoMemoryErr
);
112 *subset_ptr
= new_subset
;
118 _subset_forget(&new_subset
);
122 //======================================================================================================================
125 mdns_set_remove(const mdns_set_t me
, const uintptr_t subset_id
, const mdns_object_t object
)
127 _subset_t
*subset_ptr
;
129 for (subset_ptr
= &me
->list
; (subset
= *subset_ptr
) != NULL
; subset_ptr
= &subset
->next
) {
130 if (subset
->ident
== subset_id
) {
135 require_action_quiet(subset
, exit
, err
= kNotFoundErr
);
139 for (item_ptr
= &subset
->list
; (item
= *item_ptr
) != NULL
; item_ptr
= &item
->next
) {
140 if (item
->object
== object
) {
144 require_action_quiet(item
, exit
, err
= kNotFoundErr
);
146 *item_ptr
= item
->next
;
150 *subset_ptr
= subset
->next
;
151 _subset_forget(&subset
);
159 //======================================================================================================================
162 mdns_set_get_count(const mdns_set_t me
, const uintptr_t subset_id
)
165 for (subset
= me
->list
; subset
; subset
= subset
->next
) {
166 if (subset
->ident
== subset_id
) {
167 return subset
->count
;
173 //======================================================================================================================
176 mdns_set_iterate(const mdns_set_t me
, const uintptr_t subset_id
, mdns_set_applier_t applier
)
178 _subset_t subset
= me
->list
;
179 while (subset
&& (subset
->ident
!= subset_id
)) {
180 subset
= subset
->next
;
182 require_quiet(subset
, exit
);
184 for (_item_t item
= subset
->list
; item
; item
= item
->next
) {
185 const bool stop
= applier(item
->object
);
195 //======================================================================================================================
196 // MARK: - Set Private Methods
199 _mdns_set_copy_description(const mdns_set_t me
, __unused
const bool debug
, __unused
const bool privacy
)
201 char * description
= NULL
;
204 const char * const lim
= &buffer
[countof(buffer
)];
208 n
= mdns_snprintf_add(&dst
, lim
, "<%s: %p>: ", me
->base
.kind
->name
, me
);
209 require_quiet(n
>= 0, exit
);
211 description
= strdup(buffer
);
216 //======================================================================================================================
219 _mdns_set_finalize(const mdns_set_t me
)
222 while ((subset
= me
->list
) != NULL
) {
223 me
->list
= subset
->next
;
224 _subset_free(subset
);
228 //======================================================================================================================
229 // MARK: - Internal Helper Functions
232 _subset_create(const uintptr_t subset_id
)
234 const _subset_t obj
= (_subset_t
)calloc(1, sizeof(*obj
));
235 require_quiet(obj
, exit
);
237 obj
->ident
= subset_id
;
243 //======================================================================================================================
246 _subset_free(const _subset_t me
)
250 while ((item
= me
->list
) != NULL
) {
251 me
->list
= item
->next
;
257 //======================================================================================================================
260 _item_create(mdns_object_t object
)
262 const _item_t obj
= (_item_t
)calloc(1, sizeof(*obj
));
263 require_quiet(obj
, exit
);
265 obj
->object
= object
;
266 mdns_retain(obj
->object
);
272 //======================================================================================================================
275 _item_free(const _item_t me
)
278 mdns_forget(&me
->object
);