+++ /dev/null
-/*
- * 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 <security_utilities/utilities.h>
-#include <security_utilities/threading.h>
-#include <map>
-
-
-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 <class Ad>
- Ad *getAdornment(Key key) const
- { return safe_cast<Ad *>(getAdornment(key)); }
-
- template <class Ad>
- Ad *swapAdornment(Key key, Ad *ad)
- { return safe_cast<Ad *>(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 <class T> T &adornment(Key key);
- template <class T, class Arg1> T &adornment(Key key, Arg1 &arg1);
- template <class T, class Arg1, class Arg2> T &adornment(Key key, Arg1 &arg1, Arg2 &arg2);
- template <class T, class Arg1, class Arg2, class Arg3> T &adornment(Key key, Arg1 &arg1, Arg2 &arg2, Arg3 &arg3);
-
- // attached-value interface
- template <class T> T &attachment(Key key);
- template <class T, class Arg1> T &attachment(Key key, Arg1 arg1);
-
-private:
- Adornment *&adornmentSlot(Key key);
-
- template <class Type>
- struct Attachment : public Adornment {
- Attachment() { }
- template <class Arg1> Attachment(Arg1 arg) : mValue(arg) { }
- Type mValue;
- };
-
-private:
- typedef std::map<Key, Adornment *> AdornmentMap;
- AdornmentMap *mAdornments;
-};
-
-
-//
-// Out-of-line implementations
-//
-template <class T> T &
-Adornable::adornment(Key key)
-{
- Adornment *&slot = adornmentSlot(key);
- if (!slot)
- slot = new T;
- return dynamic_cast<T &>(*slot);
-}
-
-template <class T, class Arg1> T &
-Adornable::adornment(Key key, Arg1 &arg1)
-{
- Adornment *&slot = adornmentSlot(key);
- if (!slot)
- slot = new T(arg1);
- return dynamic_cast<T &>(*slot);
-}
-
-template <class T, class Arg1, class Arg2> T &
-Adornable::adornment(Key key, Arg1 &arg1, Arg2 &arg2)
-{
- Adornment *&slot = adornmentSlot(key);
- if (!slot)
- slot = new T(arg1, arg2);
- return dynamic_cast<T &>(*slot);
-}
-
-template <class T, class Arg1, class Arg2, class Arg3> 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<T &>(*slot);
-}
-
-template <class T>
-T &Adornable::attachment(Key key)
-{
- typedef Attachment<T> Attach;
- Adornment *&slot = adornmentSlot(key);
- if (!slot)
- slot = new Attach;
- return safe_cast<Attach *>(slot)->mValue;
-}
-
-template <class T, class Arg1>
-T &Adornable::attachment(Key key, Arg1 arg1)
-{
- typedef Attachment<T> Attach;
- Adornment *&slot = adornmentSlot(key);
- if (!slot)
- slot = new Attach(arg1);
- return safe_cast<Attach *>(slot)->mValue;
-}
-
-
-} // end namespace Security
-
-#endif //_H_ADORNMENTS