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