1 /* 2 * Copyright (c) 2021-2023 Apple Inc. All rights reserved. 3 * 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 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 #ifndef REF_COUNT_H 18 #define REF_COUNT_H 19 20 //====================================================================================================================== 21 // MARK: - Headers 22 23 //#include "dnssec_common.h" 24 #include <stdbool.h> 25 #include <stdint.h> 26 #include <stddef.h> // For offsetof(). 27 28 #include "general.h" 29 #include "nullability.h" 30 #include "dns_assert_macros.h" 31 32 //====================================================================================================================== 33 // MARK: - General Object Helpers 34 35 #define OBJECT_TYPEDEF_OPAQUE_POINTER(NAME) typedef struct NAME ## _s * NAME ## _t 36 37 // Check if structure `struct <NAME>_s` starts with structure `struct <BASE_NAME>_s <BASE_NAME>;` as the first member. 38 #define OBJECT_BASE_CHECK(NAME, BASE_NAME) \ 39 check_compile_time(offsetof(struct NAME ## _s, base) == 0); \ 40 check_compile_time(sizeof(((struct NAME ## _s *)0)->base) == sizeof(struct BASE_NAME ## _s)); \ 41 extern int8_t _obj_base_type_check[sizeof(&(((NAME ## _t)0)->base) == ((BASE_NAME ## _t)0))] \ 42 43 #ifndef STRUCT_PTR_DECLARE 44 #define STRUCT_PTR_DECLARE(STRUCT_NAME) struct STRUCT_NAME ## _s * NULLABLE STRUCT_NAME 45 #endif 46 47 #ifndef STRUCT_ARRAY_PTR_DECLARE 48 #define STRUCT_ARRAY_PTR_DECLARE(STRUCT_NAME) struct STRUCT_NAME ## _s * NULLABLE * NULLABLE STRUCT_NAME ## s 49 #endif 50 51 typedef enum { 52 compare_result_less = -1, 53 compare_result_equal = 0, 54 compare_result_greater = 1, 55 compare_result_notequal, // Can ensure that the objects being compared are not equal. Do not know about the exact order. 56 compare_result_unknown, // Unable to determine the comparison result. 57 } compare_result_t; 58 59 typedef enum { 60 sort_order_ascending, 61 sort_order_descending 62 } sort_order_t; 63 64 //====================================================================================================================== 65 // MARK: - Reference Count Object Helper Macros 66 67 // The macros below provide a way to define a reference counted object that comes with comparator and finalizer. 68 // To define a new reference counted object: 69 // 1. In the definition of the `ref_count_obj_any_t`, add `REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(<object family name>);` 70 // to declare that the object family supports reference count and all the methods provided by `ref_count.h` can be 71 // used by the object family. 72 // 2. Create a header/source file for the object family, define the retain method, release method and compare method for 73 // the object family. This step ensures that all the objects under the same family can be retained, released and 74 // compared, without having to call the underlying ref_count object base. This provides an additional layer of type 75 // check. 76 // 3. In the definition of the `ref_count_obj_any_t`, add `REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(<object family name>, 77 // <object type name>);`. This step ensures that this new reference counted object supports the comparator and the 78 // finalizer defined by `ref_count.h`. 79 // 4. Put `REF_COUNT_OBJECT_DEFINE_FULL(<object family name>, <object type name>);` in the .c file of the object. 80 // 5. Define a structure with name of `struct <object family name>_<object type name>_s` in the .c file of the object. 81 // The structure should start with `struct ref_count_obj_s base;` so that it can have reference count and object 82 // property. 83 // 6. Implement the comparator and the finalizer in the .c file of the object. 84 // 85 // Note: If an object family has been defined previously, start from step 3. 86 87 // Declare a initializer for the reference counted object. 88 #define REF_COUNT_OBJECT_DECLARE_INITIALIZER(FAMILY_NAME, NAME) \ 89 static void \ 90 _ ## FAMILY_NAME ## _ ## NAME ## _initialize(FAMILY_NAME ## _ ## NAME ## _t NONNULL object) 91 92 //====================================================================================================================== 93 94 95 // Declare a comparator for the reference counted object. 96 #define REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, NAME) \ 97 static compare_result_t \ 98 _ ## FAMILY_NAME ## _ ## NAME ## _compare(FAMILY_NAME ## _ ## NAME ## _t NONNULL object1, \ 99 FAMILY_NAME ## _ ## NAME ## _t NONNULL object2, \ 100 bool check_equality_only) 101 102 //====================================================================================================================== 103 104 // Declare a finalizer for the reference counted object. 105 #define REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, NAME) \ 106 static void \ 107 _ ## FAMILY_NAME ## _ ## NAME ## _finalize(FAMILY_NAME ## _ ## NAME ## _t NONNULL object) 108 109 //====================================================================================================================== 110 111 // Define a New() function for the reference count object to allocate the memory and initialize the memory. 112 #define REF_COUNT_OBJECT_DEFINE_NEW_FUNC(FAMILY_NAME, NAME) \ 113 static FAMILY_NAME ## _ ## NAME ## _t \ 114 _ ## FAMILY_NAME ## _ ## NAME ## _new(void) \ 115 { \ 116 const FAMILY_NAME ## _ ## NAME ## _t obj = (FAMILY_NAME ## _ ## NAME ## _t)ref_count_obj_alloc(sizeof(*obj));\ 117 if (obj == NULL) { \ 118 return NULL; \ 119 } \ 120 \ 121 ref_count_obj_init(obj, &_ ## FAMILY_NAME ## _ ## NAME ## _kind); \ 122 ref_count_obj_retain(obj); \ 123 return obj; \ 124 } \ 125 extern int8_t _dummy_variable_to_enforce_semicolon 126 127 //====================================================================================================================== 128 129 // Define the kind instance of the reference count object. 130 #define REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_BASIC(FAMILY_NAME, NAME, ...) \ 131 const struct ref_count_kind_s _ ## FAMILY_NAME ## _ ## NAME ## _kind = { \ 132 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN() \ 133 .superkind = &ref_count_kind, \ 134 .name = # FAMILY_NAME "_" # NAME, \ 135 .finalize = _ ## FAMILY_NAME ## _ ## NAME ## _finalize, \ 136 __VA_ARGS__ \ 137 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END() \ 138 }; \ 139 OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## NAME, ref_count_obj) 140 141 #define REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE(FAMILY_NAME, NAME) \ 142 REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_BASIC(FAMILY_NAME, NAME, \ 143 .compare = _ ## FAMILY_NAME ## _ ## NAME ## _compare, \ 144 ) 145 146 #define REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_WITH_INIT(FAMILY_NAME, NAME) \ 147 REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_BASIC(FAMILY_NAME, NAME, \ 148 .init = _ ## FAMILY_NAME ## _ ## NAME ## _initialize \ 149 ) 150 151 //====================================================================================================================== 152 153 // Define a reference count enabled object. 154 #define REF_COUNT_OBJECT_DEFINE_FULL(FAMILY_NAME, NAME) \ 155 REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, NAME); \ 156 REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, NAME); \ 157 REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE(FAMILY_NAME, NAME); \ 158 REF_COUNT_OBJECT_DEFINE_NEW_FUNC(FAMILY_NAME, NAME) 159 160 #define REF_COUNT_OBJECT_DEFINE_WITH_INIT_WITHOUT_COMPARATOR(FAMILY_NAME, NAME) \ 161 REF_COUNT_OBJECT_DECLARE_INITIALIZER(FAMILY_NAME, NAME); \ 162 REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, NAME); \ 163 REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_WITH_INIT(FAMILY_NAME, NAME); \ 164 REF_COUNT_OBJECT_DEFINE_NEW_FUNC(FAMILY_NAME, NAME) 165 166 167 //====================================================================================================================== 168 // MARK: - Subkind of Reference Counted Object Helper Macros 169 170 // The macros below provide a way to define an object that is a subkind of the reference count object that is defined by 171 // the macros above. 172 173 // Define a new kind type for the reference count object so that its subkind can reference it. `...` are the additional 174 // members needed for the kind type. 175 // This is the way how the subkind know what super kind it has. 176 #define REF_COUNT_OBJECT_DEFINE_KIND_TYPE_FOR_SUBKIND(FAMILY_NAME, NAME, ...) \ 177 typedef const struct FAMILY_NAME ## _ ## NAME ## _kind_s * FAMILY_NAME ## _ ## NAME ## _kind_t; \ 178 struct FAMILY_NAME ## _ ## NAME ## _kind_s { \ 179 struct ref_count_kind_s base; \ 180 FAMILY_NAME ## _ ## NAME ## _init_fields_f NONNULL FAMILY_NAME ## _ ## NAME ## _init_fields; \ 181 __VA_ARGS__ \ 182 }; \ 183 OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## NAME ## _kind, ref_count_kind); \ 184 extern const struct ref_count_kind_s _ ## FAMILY_NAME ## _ ## NAME ## _kind 185 186 //====================================================================================================================== 187 188 // Define the kind instance for the subkind of the reference count object. The reference count object has to exist 189 // before its subkind can be defined. There are four variations of the helper: 190 // 1. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_ABSTRUCT: the subkind does not need to implement comparator and finalizer. 191 // 2. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_FINALIZER: the subkind does not need to implement finalizer, 192 // but it needs to implement comparator. 193 // 3. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_COMPARATOR: the subkind does not need to implement 194 // comparator, but it needs to implement finalizer. 195 // 4. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_FULL: the subkind needs to implement both comparator and finalizer. 196 // 197 // No comparator subkind use case: it means that the super kind of the subkind already has a comparator and no more 198 // specific comparator needed. 199 // No finalizer subkind use case: it means that the subkind does not allocate new memory for its new member when doing 200 // member initialization. Therefore, there is no need for such subkind to define a finalizer that does nothing. 201 202 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_ABSTRUCT(FAMILY_NAME, SUPER, NAME, ...) \ 203 const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = { \ 204 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN() \ 205 .base = { \ 206 .superkind = &_ ## FAMILY_NAME ## _ ## SUPER ## _kind, \ 207 .name = # FAMILY_NAME "_" # SUPER "_" # NAME, \ 208 }, \ 209 .FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields, \ 210 __VA_ARGS__ \ 211 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END() \ 212 }; \ 213 OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER) 214 215 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_FINALIZER(FAMILY_NAME, SUPER, NAME, ...) \ 216 const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = { \ 217 .base = { \ 218 .superkind = &_ ## FAMILY_NAME ## _ ## SUPER ## _kind, \ 219 .name = # FAMILY_NAME "_" # SUPER "_" # NAME, \ 220 .compare = _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _compare, \ 221 }, \ 222 .FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields, \ 223 __VA_ARGS__ \ 224 }; \ 225 OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER) 226 227 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_COMPARATOR(FAMILY_NAME, SUPER, NAME, ...) \ 228 const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = { \ 229 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN() \ 230 .base = { \ 231 .superkind = &_ ## FAMILY_NAME ## _ ## SUPER ## _kind, \ 232 .name = # FAMILY_NAME "_" # SUPER "_" # NAME, \ 233 .finalize = _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _finalize \ 234 }, \ 235 .FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields, \ 236 __VA_ARGS__ \ 237 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END() \ 238 }; \ 239 OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER) 240 241 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_FULL(FAMILY_NAME, SUPER, NAME, ...) \ 242 const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = { \ 243 .base = { \ 244 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN() \ 245 .superkind = &_ ## FAMILY_NAME ## _ ## SUPER ## _kind, \ 246 .name = # FAMILY_NAME "_" # SUPER "_" # NAME, \ 247 .compare = _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _compare, \ 248 .finalize = _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _finalize \ 249 MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END() \ 250 }, \ 251 .FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields, \ 252 __VA_ARGS__ \ 253 }; \ 254 OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER) 255 256 //====================================================================================================================== 257 258 // Define a New() function for the subkind of reference count object to allocate the memory and initialize the memory. 259 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME) \ 260 static FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _t \ 261 _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _new(void) \ 262 { \ 263 const FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _t obj = (FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _t)ref_count_obj_alloc(sizeof(*obj));\ 264 if (obj == NULL) { \ 265 return NULL; \ 266 } \ 267 \ 268 ref_count_obj_init(obj, &_ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind.base); \ 269 ref_count_obj_retain(obj); \ 270 return obj; \ 271 } \ 272 extern int8_t _dummy_variable_to_enforce_semicolon 273 274 //====================================================================================================================== 275 276 // Define a subkind object of the reference counted object, based on whether the subkind needs the comparator and 277 // the finalizer. `...` are the additional member that the kind type of reference counted object needs to initialize 278 // for this subkind. 279 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_FULL(FAMILY_NAME, SUPER, NAME, ...) \ 280 REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, SUPER ## _ ## NAME); \ 281 REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, SUPER ## _ ## NAME); \ 282 REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_FULL(FAMILY_NAME, SUPER, NAME, __VA_ARGS__); \ 283 REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME) 284 285 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_WITHOUT_COMPARATOR(FAMILY_NAME, SUPER, NAME, ...) \ 286 REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, SUPER ## _ ## NAME); \ 287 REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_COMPARATOR(FAMILY_NAME, SUPER, NAME, __VA_ARGS__); \ 288 REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME) 289 290 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_WITHOUT_FINALIZER(FAMILY_NAME, SUPER, NAME, ...) \ 291 REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, SUPER ## _ ## NAME); \ 292 REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_FINALIZER(FAMILY_NAME, SUPER, NAME, __VA_ARGS__); \ 293 REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME) 294 295 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_ABSTRUCT(FAMILY_NAME, SUPER, NAME, ...) \ 296 REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_ABSTRUCT(FAMILY_NAME, SUPER, NAME, __VA_ARGS__); \ 297 REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME) 298 299 //====================================================================================================================== 300 // MARK: - Reference Counted Object Declaration 301 302 #define REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(FAMILY_NAME) STRUCT_PTR_DECLARE(FAMILY_NAME) 303 #define REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, NAME) STRUCT_PTR_DECLARE(FAMILY_NAME ## _ ## NAME) 304 #define REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(FAMILY_NAME, SUPER, NAME) REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, SUPER ## _ ## NAME) 305 306 #define REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_FAMILY(FAMILY_NAME) STRUCT_ARRAY_PTR_DECLARE(FAMILY_NAME) 307 #define REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, NAME) STRUCT_ARRAY_PTR_DECLARE(FAMILY_NAME ## _ ## NAME) 308 #define REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(FAMILY_NAME, SUPER, NAME) REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, SUPER ## _ ## NAME) 309 310 typedef union { 311 // The universal reference count enabled object. 312 STRUCT_PTR_DECLARE(ref_count_obj); 313 314 // -------- The DNS Object families -------- 315 REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(dns_obj); 316 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_obj, domain_name); 317 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_obj, rr); 318 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, cname); // CNAME RR 319 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, soa); // SOA RR 320 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, srv); // SRV RR 321 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, nsec); // NSEC RR 322 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, ds); // DS RR 323 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, rrsig); // RRSIG RR 324 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, dnskey); // DNSKEY RR 325 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, nsec3); // NSEC3 RR 326 327 // -------- The DNSSEC Object families -------- 328 REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(dnssec_obj); 329 // The validation task manager object in the DNSSEC Object families. 330 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, validation_manager); 331 // The callback context object in the DNSSEC Object families. 332 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, context); 333 // The trust anchor object in the DNSSEC Object families. 334 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, trust_anchor); 335 // The trust anchor manager object in the DNSSEC Object families. 336 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, trust_anchor_manager); 337 // The domain name object in the DNSSEC Object families. 338 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, domain_name); 339 // The resource record set object in the DNSSEC Object families. 340 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rrset); 341 // The resource record validator object in the DNSSEC Object families. 342 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rr_validator); 343 // The denial of existence object in the DNSSEC Object families. 344 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, denial_of_existence); 345 // The resource record and its subkind object in the DNSSEC Object families. 346 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rr); 347 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, cname); // CNAME RR 348 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, soa); // SOA RR 349 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, srv); // SRV RR 350 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec); // NSEC RR 351 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, ds); // DS RR 352 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, rrsig); // RRSIG RR 353 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, dnskey); // DNSKEY RR 354 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec3); // NSEC3 RR 355 356 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, resource_record_member); 357 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, dns_question_member); 358 359 // -------- The DNS Push Object families -------- 360 REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(dns_push_obj); 361 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, context); 362 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, discovered_service_manager); 363 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, dns_question_member); 364 REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, resource_record_member); 365 366 } ref_count_obj_any_t __attribute__((__transparent_union__)); 367 368 typedef union { 369 // The universal reference count enabled objects array. 370 STRUCT_ARRAY_PTR_DECLARE(ref_count_obj); 371 372 // -------- The DNSSEC Object array families -------- 373 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_FAMILY(dnssec_obj); 374 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(dnssec_obj, domain_name); // domain names array 375 376 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rr); // RRs array 377 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec); // NSEC RRs array 378 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, dnskey); // DNSKEY RRs array 379 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec3); // NSEC3 RRs array 380 381 // -------- The DNS Object families -------- 382 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_FAMILY(dns_obj); 383 REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(dns_obj, domain_name); // domain names array 384 385 } ref_count_objs_any_t __attribute__((__transparent_union__)); 386 387 //====================================================================================================================== 388 // MARK: - The Reference Count Structure Base 389 390 typedef void 391 (*ref_count_init_f)(ref_count_obj_any_t object); 392 393 typedef compare_result_t 394 (*ref_count_compare_f)(ref_count_obj_any_t object1, ref_count_obj_any_t object2, bool check_equality_only); 395 396 typedef void 397 (*ref_count_finalize_f)(ref_count_obj_any_t object); 398 399 typedef const struct ref_count_kind_s *ref_count_kind_t; 400 struct ref_count_kind_s { 401 ref_count_kind_t NULLABLE superkind; // Points to the kind instance of the super kind. 402 const char * NONNULL name; // The name of the current kind. Just for information purpose. 403 ref_count_init_f NULLABLE init; // The memory initialization method, most of time it will be NULL. 404 ref_count_compare_f NULLABLE compare; // The comparator of the kind. 405 ref_count_finalize_f NULLABLE finalize; // The finalizer of the kind. 406 }; 407 // Note the difference between memory initialization and member(field) initialization, memory initialization will 408 // initialize the allocated memory to a default value, for example, zero. However, member(field) initialization will 409 // initialize the specific object's member to a meaningful value. Most of time, memory initialization is unnecessary 410 // since we are using calloc() to reset the allocated memory to zero, the memory initialization has been finished and no 411 // need to explicitly define an initializer. However, under some cases where zero is a meaningful value, for example, 412 // socket value 0. We have to explicitly define the memory initialization method so that the member can be set to an 413 // invalid value, such as -1 for socket. We need the member to have a INVALID value because the finalizer needs to know 414 // if it needs to do some clean up. If the member has an INVALID value, the finalizer does not need to free any resource 415 // possibly related to it. This allow us to release the object immediately after allocating memory for it, even before 416 // initializing its member. (the member initialization). 417 418 extern const struct ref_count_kind_s ref_count_kind; // ref_count_kind is defined in ref_count.c 419 420 typedef struct ref_count_obj_s * ref_count_obj_t; 421 422 struct ref_count_obj_s { 423 uint32_t ref_count; 424 ref_count_kind_t NONNULL kind; 425 }; 426 427 //====================================================================================================================== 428 // MARK: - Object Methods 429 430 /*! 431 * @brief 432 * Allocate the memory for the reference counted object. 433 * 434 * @param size 435 * The size of the object to be allocated. 436 * 437 * @result 438 * The memory allocated for the object, or <code>NULL</code> if the memory allocation fails. 439 */ 440 ref_count_obj_t NULLABLE 441 ref_count_obj_alloc(size_t size); 442 443 /*! 444 * @brief 445 * Set the object's kind and do memory initialization. Under most of cases, memory initialization will not be performed. (zero initialization is already finished by 446 * <code>ref_count_obj_alloc()(</code>). 447 * 448 * @param ref_count_object 449 * The newly allocated reference counted object. 450 * 451 * @param new_kind 452 * The kind of this newly allocated reference counted object. 453 * 454 * @discussion 455 * Any newly allocated object has to call this function to set its kind. 456 */ 457 void 458 ref_count_obj_init(ref_count_obj_any_t ref_count_object, ref_count_kind_t NONNULL new_kind); 459 460 /*! 461 * @brief 462 * Retain a reference counted object by increasing the reference count by one. 463 * 464 * @param ref_count_object 465 * The supported reference counted object contained in <code>ref_count_obj_any_t</code> union. 466 * 467 * @result 468 * The retained reference counted object. 469 */ 470 ref_count_obj_t NONNULL 471 ref_count_obj_retain(ref_count_obj_any_t ref_count_object); 472 473 /*! 474 * @brief 475 * Release a reference counted object by increasing the reference count by one. If the reference count becomes zero after releasing, the object will be 476 * finalized. 477 * 478 * @param ref_count_object 479 * The supported reference counted object contained in <code>ref_count_obj_any_t</code> union. 480 */ 481 void 482 ref_count_obj_release(ref_count_obj_any_t ref_count_object); 483 484 /*! 485 * @brief 486 * Compare two reference counted objects, based on the definition of the comparator of the object. 487 * 488 * @param ref_count_object1 489 * The supported reference counted object contained in <code>ref_count_obj_any_t</code> union. 490 * 491 * @param ref_count_object2 492 * The supported reference counted object contained in <code>ref_count_obj_any_t</code> union. 493 * 494 * @param check_equality_only 495 * Indicate whether the caller only wants to know if the two objects are equal or not. The comparison will be faster when it is true. 496 * 497 * @result 498 * <code>compare_result_less</code> if <code>ref_count_object1</code> is less than <code>ref_count_object2</code>. 499 * <code>compare_result_equal</code> if <code>ref_count_object1</code> is equal to <code>ref_count_object2</code>. 500 * <code>compare_result_greater</code> if <code>ref_count_object1</code> is greater than <code>ref_count_object2</code>. 501 * <code>compare_result_notequal</code> if two objects can be compared and they are not equal, but the specific order of the two objects cannot be determined. 502 * <code>compare_result_unknown</code> if two objects have different kind or no any comparator available to determine the comparison result, or any unexpected 503 * cases defined by the comparator. 504 * 505 * @discussion 506 * If the kind of the two objects has no comparator defined, the comparator of the super kind will be used to determine their equality. Such process will 507 * continue until one available comparator is found or the root kind (NULL) is reached. If no comparator is available for the current kind, the result will be 508 * <code>compare_result_unknown</code>. 509 */ 510 compare_result_t 511 ref_count_obj_compare(ref_count_obj_any_t ref_count_object1, ref_count_obj_any_t ref_count_object2, bool check_equality_only); 512 513 /*! 514 * @brief 515 * Sort the reference counted objects array by the ascending or descending order. 516 * 517 * @param ref_count_objects 518 * The reference counted object array to be sorted. 519 * 520 * @param count 521 * The number of objects in the array. 522 * 523 * @param order 524 * The order of the sorted array, it can be 525 * <code>sort_order_ascending</code> for the ascending order. 526 * <code>sort_order_descending</code> for the descending order. 527 * 528 * @discussion 529 * The object has to have a comparator that can determine the specific order of the two objects that have the same kind, in order to be sortable. If no 530 * comparator is available or the comparator can only determine the equality of the objects, the array will be returned untouched. 531 */ 532 void 533 ref_count_objs_sort(ref_count_objs_any_t ref_count_objects, size_t count, sort_order_t order); 534 535 #endif // REF_COUNT_H 536