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 █ 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