]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/cfclass.cpp
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / cfclass.cpp
1 /*
2 * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <security_utilities/cfclass.h>
25 #include <security_utilities/seccfobject.h>
26 #include <security_utilities/threading.h>
27 #include <CoreFoundation/CFString.h>
28 #include <sys/time.h>
29
30 //
31 // CFClass
32 //
33 CFClass::CFClass(const char *name)
34 {
35 // initialize the CFRuntimeClass structure
36 version = 0;
37 className = name;
38 init = NULL;
39 copy = NULL;
40 finalize = finalizeType;
41 equal = equalType;
42 hash = hashType;
43 copyFormattingDesc = copyFormattingDescType;
44 copyDebugDesc = copyDebugDescType;
45
46 // update because we are now doing our own reference counting
47 version |= _kCFRuntimeCustomRefCount; // see ma, no hands!
48 refcount = refCountForType;
49
50 // register
51 typeID = _CFRuntimeRegisterClass(this);
52 assert(typeID != _kCFRuntimeNotATypeID);
53 }
54
55 uint32_t
56 CFClass::cleanupObject(intptr_t op, CFTypeRef cf, bool &zap)
57 {
58 // the default is to not throw away the object
59 zap = false;
60
61 uint32_t currentCount;
62 SecCFObject *obj = SecCFObject::optional(cf);
63
64 uint32_t oldCount;
65 currentCount = obj->updateRetainCount(op, &oldCount);
66
67 if (op == 0)
68 {
69 return currentCount;
70 }
71 else if (currentCount == 0)
72 {
73 // we may not be able to delete if the caller has active children
74 if (obj->mayDelete())
75 {
76 finalizeType(cf);
77 zap = true; // ask the caller to release the mutex and zap the object
78 return 0;
79 }
80 else
81 {
82 return currentCount;
83 }
84 }
85 else
86 {
87 return 0;
88 }
89 }
90
91 uint32_t
92 CFClass::refCountForType(intptr_t op, CFTypeRef cf) throw()
93 {
94 uint32_t result = 0;
95 bool zap = false;
96
97 try
98 {
99 SecCFObject *obj = SecCFObject::optional(cf);
100 Mutex* mutex = obj->getMutexForObject();
101 if (mutex == NULL)
102 {
103 // if the object didn't have a mutex, it wasn't cached.
104 // Just clean it up and get out.
105 result = cleanupObject(op, cf, zap);
106 }
107 else
108 {
109 // we have a mutex, so we need to do our cleanup operation under its control
110 StLock<Mutex> _(*mutex);
111 result = cleanupObject(op, cf, zap);
112 }
113
114 if (zap) // did we release the object?
115 {
116 delete obj; // should call the overloaded delete for the object
117 }
118 }
119 catch (...)
120 {
121 }
122
123 // keep the compiler happy
124 return result;
125 }
126
127
128
129 void
130 CFClass::finalizeType(CFTypeRef cf) throw()
131 {
132 /*
133 We need to control the lifetime of the object. This means
134 that the cache lock has to be asserted while we are determining if the
135 object should live or die. The mutex is recursive, which means that
136 we won't end up with mutex inversion.
137 */
138
139 SecCFObject *obj = SecCFObject::optional(cf);
140
141 try
142 {
143 Mutex* mutex = obj->getMutexForObject();
144 if (mutex == NULL)
145 {
146 // if the object didn't have a mutex, it wasn't cached.
147 // Just clean it up and get out.
148 obj->aboutToDestruct(); // removes the object from its associated cache.
149 }
150 else
151 {
152 StLock<Mutex> _(*mutex);
153
154 if (obj->isNew())
155 {
156 // New objects aren't in the cache.
157 // Just clean it up and get out.
158 obj->aboutToDestruct(); // removes the object from its associated cache.
159 return;
160 }
161
162 obj->aboutToDestruct(); // removes the object from its associated cache.
163 }
164 }
165 catch(...)
166 {
167 }
168 }
169
170 Boolean
171 CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw()
172 {
173 // CF checks for pointer equality and ensures type equality already
174 try {
175 return SecCFObject::optional(cf1)->equal(*SecCFObject::optional(cf2));
176 } catch (...) {
177 return false;
178 }
179 }
180
181 CFHashCode
182 CFClass::hashType(CFTypeRef cf) throw()
183 {
184 try {
185 return SecCFObject::optional(cf)->hash();
186 } catch (...) {
187 return 666; /* Beasty return for error */
188 }
189 }
190
191 CFStringRef
192 CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw()
193 {
194 try {
195 return SecCFObject::optional(cf)->copyFormattingDesc(dict);
196 } catch (...) {
197 return CFSTR("Exception thrown trying to format object");
198 }
199 }
200
201 CFStringRef
202 CFClass::copyDebugDescType(CFTypeRef cf) throw()
203 {
204 try {
205 return SecCFObject::optional(cf)->copyDebugDesc();
206 } catch (...) {
207 return CFSTR("Exception thrown trying to format object");
208 }
209 }
210
211