X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_utilities/lib/utilities.h diff --git a/Security/libsecurity_utilities/lib/utilities.h b/Security/libsecurity_utilities/lib/utilities.h new file mode 100644 index 00000000..2bd28d56 --- /dev/null +++ b/Security/libsecurity_utilities/lib/utilities.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * cssm utilities + */ +#ifndef _H_UTILITIES +#define _H_UTILITIES + +#include +#include +#include +#include +#include +#include + +namespace Security +{ + +// +// Elementary debugging support. +// #include for more debugging facilities. +// +#define IFDEBUG(it) IFELSEDEBUG(it,) +#define IFNDEBUG(it) IFELSEDEBUG(,it) + +#if defined(NDEBUG) + +# define safe_cast static_cast +# define safer_cast static_cast + +# define IFELSEDEBUG(d,nd) nd + +#else + +template +inline Derived safer_cast(Base &base) +{ + return dynamic_cast(base); +} + +template +inline Derived safe_cast(Base *base) +{ + if (base == NULL) + return NULL; // okay to cast NULL to NULL + Derived p = dynamic_cast(base); + assert(p); + return p; +} + +# define IFELSEDEBUG(d,nd) d + +#endif //NDEBUG + + +// +// Place this into your class definition if you don't want it to be copyable +// or asignable. This will not prohibit allocation on the stack or in static +// memory, but it will make anything derived from it, and anything containing +// it, fixed-once-created. A proper object, I suppose. +// +#define NOCOPY(Type) \ + private: Type(const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; \ + void operator = (const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; + + +// +// Helpers for memory pointer validation +// +#define MY_CSSM_ERRCODE_INVALID_POINTER 0x0004 +template +inline T &Required(T *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER) +{ + if (ptr == NULL) + MacOSError::throwMe(err); + return *ptr; +} + +// specialization for void * (just check for non-null; don't return a void & :-) +inline void Required(void *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER) +{ + if (ptr == NULL) + MacOSError::throwMe(err); +} + + +// +// Tools to build POD wrapper classes +// +template +class PodWrapper : public POD { +public: + // pure typecasts + static Wrapper * &overlayVar(POD * &data) + { return reinterpret_cast(data); } + static const Wrapper * &overlayVar(const POD * &data) + { return reinterpret_cast(data); } + + static Wrapper *overlay(POD *data) + { return static_cast(data); } + static const Wrapper *overlay(const POD *data) + { return static_cast(data); } + static Wrapper &overlay(POD &data) + { return static_cast(data); } + static const Wrapper &overlay(const POD &data) + { return static_cast(data); } + + // optional/required forms + static Wrapper &required(POD *data) + { return overlay(Required(data)); } + static const Wrapper &required(const POD *data) + { return overlay(Required(data)); } + static Wrapper *optional(POD *data) + { return overlay(data); } + static const Wrapper *optional(const POD *data) + { return overlay(data); } + + // general helpers for all PodWrappers + void clearPod() + { memset(static_cast(this), 0, sizeof(POD)); } + + void assignPod(const POD &source) + { static_cast(*this) = source; } +}; + + +// +// Template builder support +// +template +struct Nonconst { + typedef T Type; +}; + +template +struct Nonconst { + typedef U Type; +}; + +template +struct Nonconst { + typedef U *Type; +}; + +// cast away pointed-to constness +template +typename Nonconst::Type unconst_cast(T obj) +{ + return const_cast::Type>(obj); +} + +template +typename Nonconst::Type &unconst_ref_cast(T &obj) +{ + return const_cast::Type &>(obj); +} + + +// Help with container of something->pointer cleanup +template +static inline void for_each_delete(In first, In last) +{ + while (first != last) + delete *(first++); +} + +// Help with map of something->pointer cleanup +template +static inline void for_each_map_delete(In first, In last) +{ + while (first != last) + delete (first++)->second; +} + +// versions of copy that project to pair elements +template +inline OutIterator copy_first(InIterator first, InIterator last, OutIterator out) +{ + while (first != last) + *out++ = (first++)->first; + return out; +} + +template +inline OutIterator copy_second(InIterator first, InIterator last, OutIterator out) +{ + while (first != last) + *out++ = (first++)->second; + return out; +} + + +// simple safe re-entry blocker +class RecursionBlock { +public: + RecursionBlock() : mActive(false) { } + ~RecursionBlock() { assert(!mActive); } + +public: + class Once { + public: + Once(RecursionBlock &rb) : block(rb), mActive(false) { } + ~Once() { block.mActive &= !mActive; } + bool operator () () + { if (block.mActive) return true; mActive = block.mActive = true; return false; } + + RecursionBlock █ + + private: + bool mActive; + }; + friend class Once; + +private: + bool mActive; +}; + +// Quick and dirty template for a (temporary) array of something +// Usage example auto_array anArray(20); +template +class auto_array +{ +public: + auto_array() : mArray(NULL) {} + auto_array(size_t inSize) : mArray(new T[inSize]) {} + ~auto_array() { if (mArray) delete[] mArray; } + T &operator[](size_t inIndex) { return mArray[inIndex]; } + void allocate(size_t inSize) { if (mArray) delete[] mArray; mArray = new T[inSize]; } + T *get() { return mArray; } + T *release() { T *anArray = mArray; mArray = NULL; return anArray; } +private: + T *mArray; +}; + +// Template for a vector-like class that takes a c-array as it's +// underlying storage without making a copy. +template +class constVector +{ + NOCOPY(constVector<_Tp>) +public: + typedef _Tp value_type; + typedef const value_type* const_pointer; + typedef const value_type* const_iterator; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef std::reverse_iterator const_reverse_iterator; +public: + const_iterator begin() const { return _M_start; } + const_iterator end() const { return _M_finish; } + + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + size_type size() const + { return size_type(end() - begin()); } + bool empty() const + { return begin() == end(); } + + const_reference operator[](size_type __n) const { return *(begin() + __n); } + + // "at" will eventually have range checking, once we have the + // infrastructure to be able to throw stl range errors. + const_reference at(size_type n) const { return (*this)[n]; } + + constVector(size_type __n, const _Tp* __value) + : _M_start(__value), _M_finish(__value + __n) + {} + + constVector() : _M_start(NULL), _M_finish(NULL) {} + + void overlay(size_type __n, const _Tp* __value) { + _M_start = __value; + _M_finish = __value + __n; + } + + const_reference front() const { return *begin(); } + const_reference back() const { return *(end() - 1); } +private: + const _Tp *_M_start; + const _Tp *_M_finish; +}; + +char *cached_realpath(const char * file_name, char * resolved_name); + +} // end namespace Security + + +#endif //_H_UTILITIES