2 * Copyright (c) 2019 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@
26 * - assigns numbers to serviceID strings
33 #include "serviceIDNumber.h"
34 #include <CoreFoundation/CFDictionary.h>
36 #if TEST_SERVICEID_NUMBER
37 #include <SystemConfiguration/SCPrivate.h>
38 #endif /* TEST_SERVICEID_NUMBER */
41 /* dictionary to hold serviceIDNumber: key is the serviceID */
42 static CFMutableDictionaryRef S_serviceID_to_number_dict
;
44 /* dictionary to hold serviceID: key is the serviceIDNumber */
45 static CFMutableDictionaryRef S_number_to_serviceID_dict
;
48 serviceIDNumberEqual(const void * ptr1
, const void * ptr2
)
50 return (((serviceIDNumber
)ptr1
) == ((serviceIDNumber
)ptr2
));
54 serviceIDNumberCopyDescription(const void * ptr
)
56 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%ld"),
57 (serviceIDNumber
)ptr
);
61 serviceIDNumberHash(const void * ptr
) {
62 return (CFHashCode
)((serviceIDNumber
)ptr
);
65 static const CFDictionaryValueCallBacks kserviceIDNumberValueCallBacks
= {
66 0, NULL
, NULL
, serviceIDNumberCopyDescription
, serviceIDNumberEqual
69 static const CFDictionaryKeyCallBacks kserviceIDNumberKeyCallBacks
= {
70 0, NULL
, NULL
, serviceIDNumberCopyDescription
, serviceIDNumberEqual
,
75 ** S_serviceID_numbers
78 __private_extern__ Boolean
79 serviceIDNumberGetIfPresent(CFStringRef serviceID
, serviceIDNumber
*sidn
)
84 has_number
= CFDictionaryGetValueIfPresent(S_serviceID_to_number_dict
,
87 *sidn
= (serviceIDNumber
)val
;
93 * Function: serviceIDNumberGet
95 * Return the currently assigned serviceIDNumber for the given serviceID.
96 * If one is already assigned, return that. If one isn't assigned, check
97 * the next integer value after 'current_sidn', but skip zero.
98 * If that number is assigned, pick the next one.
100 static serviceIDNumber S_current_sidn
;
102 __private_extern__ serviceIDNumber
103 serviceIDNumberGet(CFStringRef serviceID
)
105 serviceIDNumber sidn
;
107 if (serviceIDNumberGetIfPresent(serviceID
, &sidn
)) {
111 /* assign a number to the serviceID */
113 if (S_current_sidn
== kserviceIDNumberZero
) {
117 /* if it's in use, skip to the next value */
118 if (CFDictionaryContainsKey(S_number_to_serviceID_dict
,
119 (const void *)S_current_sidn
)) {
122 /* it's not in use, use it */
123 sidn
= S_current_sidn
;
124 CFDictionarySetValue(S_serviceID_to_number_dict
,
125 serviceID
, (const void *)sidn
);
126 CFDictionarySetValue(S_number_to_serviceID_dict
,
127 (const void *)sidn
, serviceID
);
134 __private_extern__
void
135 serviceIDNumberRemove(CFStringRef serviceID
)
139 if (CFDictionaryGetValueIfPresent(S_serviceID_to_number_dict
, serviceID
,
141 #if TEST_SERVICEID_NUMBER
142 SCPrint(TRUE
, stdout
, CFSTR("Removing %@ %ld\n"),
143 serviceID
, (serviceIDNumber
)val
);
145 CFDictionaryRemoveValue(S_serviceID_to_number_dict
, serviceID
);
146 CFDictionaryRemoveValue(S_number_to_serviceID_dict
, val
);
150 __private_extern__
void
151 serviceIDNumberInit(void)
153 S_serviceID_to_number_dict
154 = CFDictionaryCreateMutable(NULL
, 0,
155 &kCFTypeDictionaryKeyCallBacks
,
156 &kserviceIDNumberValueCallBacks
);
157 S_number_to_serviceID_dict
158 = CFDictionaryCreateMutable(NULL
, 0,
159 &kserviceIDNumberKeyCallBacks
,
160 &kCFTypeDictionaryValueCallBacks
);
163 #if TEST_SERVICEID_NUMBER
166 my_CFUUIDStringCreate(CFAllocatorRef alloc
)
169 CFStringRef uuid_str
;
171 uuid
= CFUUIDCreate(alloc
);
172 uuid_str
= CFUUIDCreateString(alloc
, uuid
);
181 CFStringRef serviceID_list
[N_LIST
];
183 serviceIDNumberInit();
184 for (int i
= 0; i
< N_LIST
; i
++) {
185 CFStringRef serviceID
= my_CFUUIDStringCreate(NULL
);
186 serviceIDNumber sidn
;
188 /* force a collision */
191 sidn
= serviceIDNumberGet(serviceID
);
192 SCPrint(TRUE
, stdout
, CFSTR("%d: %@ %ld\n"),
194 serviceID_list
[i
] = serviceID
;
197 for (int i
= 0; i
< N_LIST
; i
++) {
198 CFStringRef serviceID
= serviceID_list
[i
];
199 serviceIDNumber sidn
;
201 if (!serviceIDNumberGetIfPresent(serviceID
, &sidn
)) {
202 SCPrint(TRUE
, stderr
, CFSTR("Failed to find %@\n"),
206 SCPrint(TRUE
, stdout
, CFSTR("%@ => %ld\n"), serviceID
, sidn
);
209 serviceIDNumber sidn
;
211 if (serviceIDNumberGetIfPresent(CFSTR("blah"), &sidn
)) {
213 "Shouldn't have been able to look that up\n");
218 for (int i
= 0; i
< N_LIST
/ 2; i
++) {
219 CFStringRef serviceID
= serviceID_list
[i
];
220 serviceIDNumber sidn
;
222 serviceIDNumberRemove(serviceID
);
223 if (serviceIDNumberGetIfPresent(serviceID
, &sidn
)) {
224 SCPrint(TRUE
, stderr
,
225 CFSTR("Found %@, but shouldn't have\n"),
231 for (int i
= 0; i
< N_LIST
; i
++) {
232 CFStringRef serviceID
= serviceID_list
[i
];
233 serviceIDNumber sidn
;
235 sidn
= serviceIDNumberGet(serviceID
);
236 SCPrint(TRUE
, stdout
, CFSTR("%d: %@ %ld\n"),
241 #endif /* TEST_SERVICEID_NUMBER */