]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/utilities.h
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / utilities.h
1 /*
2 * Copyright (c) 2000-2004,2011,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
25 /*
26 * cssm utilities
27 */
28 #ifndef _H_UTILITIES
29 #define _H_UTILITIES
30
31 #include <security_utilities/utility_config.h>
32 #include <security_utilities/errors.h>
33 #include <exception>
34 #include <new>
35 #include <string>
36 #include <string.h>
37
38 #include <security_utilities/simulatecrash_assert.h>
39
40 namespace Security
41 {
42
43 //
44 // Elementary debugging support.
45 // #include <debugging.h> for more debugging facilities.
46 //
47 #define IFDEBUG(it) IFELSEDEBUG(it,)
48 #define IFNDEBUG(it) IFELSEDEBUG(,it)
49
50 #if defined(NDEBUG)
51
52 # define safe_cast static_cast
53 # define safer_cast static_cast
54
55 # define IFELSEDEBUG(d,nd) nd
56
57 #else
58
59 template <class Derived, class Base>
60 inline Derived safer_cast(Base &base)
61 {
62 return dynamic_cast<Derived>(base);
63 }
64
65 template <class Derived, class Base>
66 inline Derived safe_cast(Base *base)
67 {
68 if (base == NULL)
69 return NULL; // okay to cast NULL to NULL
70 Derived p = dynamic_cast<Derived>(base);
71 assert(p);
72 return p;
73 }
74
75 # define IFELSEDEBUG(d,nd) d
76
77 #endif //NDEBUG
78
79
80 //
81 // Place this into your class definition if you don't want it to be copyable
82 // or asignable. This will not prohibit allocation on the stack or in static
83 // memory, but it will make anything derived from it, and anything containing
84 // it, fixed-once-created. A proper object, I suppose.
85 //
86 #define NOCOPY(Type) \
87 private: Type(const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; \
88 void operator = (const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER;
89
90
91 //
92 // Helpers for memory pointer validation
93 //
94 #define MY_CSSM_ERRCODE_INVALID_POINTER 0x0004
95 template <class T>
96 inline T &Required(T *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER)
97 {
98 if (ptr == NULL)
99 MacOSError::throwMe(err);
100 return *ptr;
101 }
102
103 // specialization for void * (just check for non-null; don't return a void & :-)
104 inline void Required(void *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER)
105 {
106 if (ptr == NULL)
107 MacOSError::throwMe(err);
108 }
109
110
111 //
112 // Tools to build POD wrapper classes
113 //
114 template <class Wrapper, class POD>
115 class PodWrapper : public POD {
116 public:
117 // pure typecasts
118 static Wrapper * &overlayVar(POD * &data)
119 { return reinterpret_cast<Wrapper * &>(data); }
120 static const Wrapper * &overlayVar(const POD * &data)
121 { return reinterpret_cast<const Wrapper * &>(data); }
122
123 static Wrapper *overlay(POD *data)
124 { return static_cast<Wrapper *>(data); }
125 static const Wrapper *overlay(const POD *data)
126 { return static_cast<const Wrapper *>(data); }
127 static Wrapper &overlay(POD &data)
128 { return static_cast<Wrapper &>(data); }
129 static const Wrapper &overlay(const POD &data)
130 { return static_cast<const Wrapper &>(data); }
131
132 // optional/required forms
133 static Wrapper &required(POD *data)
134 { return overlay(Required(data)); }
135 static const Wrapper &required(const POD *data)
136 { return overlay(Required(data)); }
137 static Wrapper *optional(POD *data)
138 { return overlay(data); }
139 static const Wrapper *optional(const POD *data)
140 { return overlay(data); }
141
142 // general helpers for all PodWrappers
143 void clearPod()
144 { memset(static_cast<POD *>(this), 0, sizeof(POD)); }
145
146 void assignPod(const POD &source)
147 { static_cast<POD &>(*this) = source; }
148 };
149
150
151 //
152 // Template builder support
153 //
154 template <class T>
155 struct Nonconst {
156 typedef T Type;
157 };
158
159 template <class U>
160 struct Nonconst<const U> {
161 typedef U Type;
162 };
163
164 template <class U>
165 struct Nonconst<const U *> {
166 typedef U *Type;
167 };
168
169 // cast away pointed-to constness
170 template <class T>
171 typename Nonconst<T>::Type unconst_cast(T obj)
172 {
173 return const_cast<typename Nonconst<T>::Type>(obj);
174 }
175
176 template <class T>
177 typename Nonconst<T>::Type &unconst_ref_cast(T &obj)
178 {
179 return const_cast<typename Nonconst<T>::Type &>(obj);
180 }
181
182
183 // Help with container of something->pointer cleanup
184 template <class In>
185 static inline void for_each_delete(In first, In last)
186 {
187 while (first != last)
188 delete *(first++);
189 }
190
191 // Help with map of something->pointer cleanup
192 template <class In>
193 static inline void for_each_map_delete(In first, In last)
194 {
195 while (first != last)
196 delete (first++)->second;
197 }
198
199 // versions of copy that project to pair elements
200 template <class InIterator, class OutIterator>
201 inline OutIterator copy_first(InIterator first, InIterator last, OutIterator out)
202 {
203 while (first != last)
204 *out++ = (first++)->first;
205 return out;
206 }
207
208 template <class InIterator, class OutIterator>
209 inline OutIterator copy_second(InIterator first, InIterator last, OutIterator out)
210 {
211 while (first != last)
212 *out++ = (first++)->second;
213 return out;
214 }
215
216
217 // simple safe re-entry blocker
218 class RecursionBlock {
219 public:
220 RecursionBlock() : mActive(false) { }
221 ~RecursionBlock() { assert(!mActive); }
222
223 public:
224 class Once {
225 public:
226 Once(RecursionBlock &rb) : block(rb), mActive(false) { }
227 ~Once() { block.mActive &= !mActive; }
228 bool operator () ()
229 { if (block.mActive) return true; mActive = block.mActive = true; return false; }
230
231 RecursionBlock &block;
232
233 private:
234 bool mActive;
235 };
236 friend class Once;
237
238 private:
239 bool mActive;
240 };
241
242 // Quick and dirty template for a (temporary) array of something
243 // Usage example auto_array<UInt32> anArray(20);
244 template <class T>
245 class auto_array
246 {
247 public:
248 auto_array() : mArray(NULL) {}
249 auto_array(size_t inSize) : mArray(new T[inSize]) {}
250 ~auto_array() { if (mArray) delete[] mArray; }
251 T &operator[](size_t inIndex) { return mArray[inIndex]; }
252 void allocate(size_t inSize) { if (mArray) delete[] mArray; mArray = new T[inSize]; }
253 T *get() { return mArray; }
254 T *release() { T *anArray = mArray; mArray = NULL; return anArray; }
255 private:
256 T *mArray;
257 };
258
259 // Template for a vector-like class that takes a c-array as it's
260 // underlying storage without making a copy.
261 template <class _Tp>
262 class constVector
263 {
264 NOCOPY(constVector<_Tp>)
265 public:
266 typedef _Tp value_type;
267 typedef const value_type* const_pointer;
268 typedef const value_type* const_iterator;
269 typedef const value_type& const_reference;
270 typedef size_t size_type;
271 typedef ptrdiff_t difference_type;
272
273 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
274 public:
275 const_iterator begin() const { return _M_start; }
276 const_iterator end() const { return _M_finish; }
277
278 const_reverse_iterator rbegin() const
279 { return const_reverse_iterator(end()); }
280 const_reverse_iterator rend() const
281 { return const_reverse_iterator(begin()); }
282
283 size_type size() const
284 { return size_type(end() - begin()); }
285 bool empty() const
286 { return begin() == end(); }
287
288 const_reference operator[](size_type __n) const { return *(begin() + __n); }
289
290 // "at" will eventually have range checking, once we have the
291 // infrastructure to be able to throw stl range errors.
292 const_reference at(size_type n) const { return (*this)[n]; }
293
294 constVector(size_type __n, const _Tp* __value)
295 : _M_start(__value), _M_finish(__value + __n)
296 {}
297
298 constVector() : _M_start(NULL), _M_finish(NULL) {}
299
300 void overlay(size_type __n, const _Tp* __value) {
301 _M_start = __value;
302 _M_finish = __value + __n;
303 }
304
305 const_reference front() const { return *begin(); }
306 const_reference back() const { return *(end() - 1); }
307 private:
308 const _Tp *_M_start;
309 const _Tp *_M_finish;
310 };
311
312 char *cached_realpath(const char * file_name, char * resolved_name);
313
314 } // end namespace Security
315
316
317 #endif //_H_UTILITIES