X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_utilities/lib/adornments.h diff --git a/OSX/libsecurity_utilities/lib/adornments.h b/OSX/libsecurity_utilities/lib/adornments.h new file mode 100644 index 00000000..bd5dccfa --- /dev/null +++ b/OSX/libsecurity_utilities/lib/adornments.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2004,2011-2012,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@ + */ + + +// +// adornment - generic attached-storage facility +// +// Adornments are dynamic objects (subclasses of class Adornment) that can +// be "attached" ("hung off") any object derived from Adornable. Any number +// of Adornments can be attached to one object using different unique keys +// (of type void *). +// +// Adornments can be used by a single caller to remember data "with" an Adornable +// object. Multiple, cooperating callers can share an Adornment as long as they +// agree on the Key. +// +// Memory management: All Adornments must be dynamically allocated, and will be +// deleted when their Adornable dies. Once attached, their memory is owned by the +// Adornable (NOT the caller). Do not get fancy with an Adornment's memory; +// trying to share one Adornment instance between Adornables or slots is bad. +// If you need shared storage, use a RefPointer attachment. +// +// Your Adornment's destructor will be called when its Adornable dies, or when +// its slot is replaced (whichever happens sooner). So you CAN get notification +// of an object's death by attaching an Adornment with a unique key and putting +// code in its destructor. +// +// It is fairly popular for a subclass of Adornable to rename its getAdornment and +// adornment methods as operator [], but we won't make that decision for you +// at this level. +// +#ifndef _H_ADORNMENTS +#define _H_ADORNMENTS + +#include +#include +#include + + +namespace Security { + +class Adornable; + + +// +// An Adornment is data "hung" (stored with) an Adornable. +// +class Adornment { + friend class Adornable; +public: + typedef const void *Key; + + virtual ~Adornment() = 0; + +protected: + Adornment() { } +}; + + +// +// An Adornable can carry Adornments, potentially a different one for each +// Key. We provide both a raw interface (dealing in Adornment subclasses), +// and an attachment form that just pretends that the Adornable has extra, +// dynamically allocated members filed under various keys. +// +class Adornable { +public: + Adornable() : mAdornments(NULL) { } + ~Adornable(); + + // adornment keys (slots) + typedef Adornment::Key Key; + + // primitive access, raw form + Adornment *getAdornment(Key key) const; // NULL if not present + void setAdornment(Key key, Adornment *ad); // use NULL to delete + Adornment *swapAdornment(Key key, Adornment *ad); // rotate in/out + + // typed primitive access. Ad must be a unique subclass of Adornment + template + Ad *getAdornment(Key key) const + { return safe_cast(getAdornment(key)); } + + template + Ad *swapAdornment(Key key, Ad *ad) + { return safe_cast(swapAdornment(key, ad)); } + + // inquiries for the Adornable itself + bool empty() const { return !mAdornments || mAdornments->empty(); } + unsigned int size() const { return mAdornments ? (unsigned int)mAdornments->size() : 0; } + void clearAdornments(); + +public: + // Adornment ref interface. Will return an (optionally constructed) Adornment &. + template T &adornment(Key key); + template T &adornment(Key key, Arg1 &arg1); + template T &adornment(Key key, Arg1 &arg1, Arg2 &arg2); + template T &adornment(Key key, Arg1 &arg1, Arg2 &arg2, Arg3 &arg3); + + // attached-value interface + template T &attachment(Key key); + template T &attachment(Key key, Arg1 arg1); + +private: + Adornment *&adornmentSlot(Key key); + + template + struct Attachment : public Adornment { + Attachment() { } + template Attachment(Arg1 arg) : mValue(arg) { } + Type mValue; + }; + +private: + typedef std::map AdornmentMap; + AdornmentMap *mAdornments; +}; + + +// +// Out-of-line implementations +// +template T & +Adornable::adornment(Key key) +{ + Adornment *&slot = adornmentSlot(key); + if (!slot) + slot = new T; + return dynamic_cast(*slot); +} + +template T & +Adornable::adornment(Key key, Arg1 &arg1) +{ + Adornment *&slot = adornmentSlot(key); + if (!slot) + slot = new T(arg1); + return dynamic_cast(*slot); +} + +template T & +Adornable::adornment(Key key, Arg1 &arg1, Arg2 &arg2) +{ + Adornment *&slot = adornmentSlot(key); + if (!slot) + slot = new T(arg1, arg2); + return dynamic_cast(*slot); +} + +template T & +Adornable::adornment(Key key, Arg1 &arg1, Arg2 &arg2, Arg3 &arg3) +{ + Adornment *&slot = adornmentSlot(key); + if (!slot) + slot = new T(arg1, arg2, arg3); + return dynamic_cast(*slot); +} + +template +T &Adornable::attachment(Key key) +{ + typedef Attachment Attach; + Adornment *&slot = adornmentSlot(key); + if (!slot) + slot = new Attach; + return safe_cast(slot)->mValue; +} + +template +T &Adornable::attachment(Key key, Arg1 arg1) +{ + typedef Attachment Attach; + Adornment *&slot = adornmentSlot(key); + if (!slot) + slot = new Attach(arg1); + return safe_cast(slot)->mValue; +} + + +} // end namespace Security + +#endif //_H_ADORNMENTS