1/*
2 * Copyright (c) 2000-2004 Apple Computer, 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
38namespace 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
57template <class Derived, class Base>
58inline Derived safer_cast(Base &base)
59{
60    return dynamic_cast<Derived>(base);
61}
62
63template <class Derived, class Base>
64inline 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
93template <class T>
94inline 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 & :-)
102inline 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//
112template <class Wrapper, class POD>
113class PodWrapper : public POD {
114public:
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//
152template <class T>
153struct Nonconst {
154	typedef T Type;
155};
156
157template <class U>
158struct Nonconst<const U> {
159	typedef U Type;
160};
161
162template <class U>
163struct Nonconst<const U *> {
164	typedef U *Type;
165};
166
167// cast away pointed-to constness
168template <class T>
169typename Nonconst<T>::Type unconst_cast(T obj)
170{
171	return const_cast<typename Nonconst<T>::Type>(obj);
172}
173
174template <class T>
175typename 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
182template <class In>
183static 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
190template <class In>
191static 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
198template <class InIterator, class OutIterator>
199inline OutIterator copy_first(InIterator first, InIterator last, OutIterator out)
200{
201	while (first != last)
202		*out++ = (first++)->first;
203	return out;
204}
205
206template <class InIterator, class OutIterator>
207inline 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
216class RecursionBlock {
217public:
218	RecursionBlock() : mActive(false) { }
219	~RecursionBlock() { assert(!mActive); }
220
221public:
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
236private:
237	bool mActive;
238};
239
240// Quick and dirty template for a (temporary) array of something
241// Usage example auto_array<UInt32> anArray(20);
242template <class T>
243class auto_array
244{
245public:
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; }
253private:
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.
259template <class _Tp>
260class constVector
261{
262    NOCOPY(constVector<_Tp>)
263public:
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;
272public:
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); }
305private:
306    const _Tp *_M_start;
307    const _Tp *_M_finish;
308};
309
310char *cached_realpath(const char * file_name, char * resolved_name);
311
312} // end namespace Security
313
314
315#endif //_H_UTILITIES
316