]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_utilities/lib/utilities.h
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / utilities.h
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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
d64be36e
A
38#include <security_utilities/simulatecrash_assert.h>
39
b1ab9ed8
A
40namespace 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
59template <class Derived, class Base>
60inline Derived safer_cast(Base &base)
61{
62 return dynamic_cast<Derived>(base);
63}
64
65template <class Derived, class Base>
66inline 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
95template <class T>
96inline 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 & :-)
104inline 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//
114template <class Wrapper, class POD>
115class PodWrapper : public POD {
116public:
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//
154template <class T>
155struct Nonconst {
156 typedef T Type;
157};
158
159template <class U>
160struct Nonconst<const U> {
161 typedef U Type;
162};
163
164template <class U>
165struct Nonconst<const U *> {
166 typedef U *Type;
167};
168
169// cast away pointed-to constness
170template <class T>
171typename Nonconst<T>::Type unconst_cast(T obj)
172{
173 return const_cast<typename Nonconst<T>::Type>(obj);
174}
175
176template <class T>
177typename 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
184template <class In>
185static 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
192template <class In>
193static 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
200template <class InIterator, class OutIterator>
201inline OutIterator copy_first(InIterator first, InIterator last, OutIterator out)
202{
203 while (first != last)
204 *out++ = (first++)->first;
205 return out;
206}
207
208template <class InIterator, class OutIterator>
209inline 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
218class RecursionBlock {
219public:
220 RecursionBlock() : mActive(false) { }
221 ~RecursionBlock() { assert(!mActive); }
222
223public:
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
238private:
239 bool mActive;
240};
241
242// Quick and dirty template for a (temporary) array of something
243// Usage example auto_array<UInt32> anArray(20);
244template <class T>
245class auto_array
246{
247public:
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; }
255private:
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.
261template <class _Tp>
262class constVector
263{
264 NOCOPY(constVector<_Tp>)
265public:
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;
274public:
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); }
307private:
308 const _Tp *_M_start;
309 const _Tp *_M_finish;
310};
311
312char *cached_realpath(const char * file_name, char * resolved_name);
313
314} // end namespace Security
315
316
317#endif //_H_UTILITIES