]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/adornments.h
2 * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // adornment - generic attached-storage facility
28 // Adornments are dynamic objects (subclasses of class Adornment) that can
29 // be "attached" ("hung off") any object derived from Adornable. Any number
30 // of Adornments can be attached to one object using different unique keys
33 // Adornments can be used by a single caller to remember data "with" an Adornable
34 // object. Multiple, cooperating callers can share an Adornment as long as they
37 // Memory management: All Adornments must be dynamically allocated, and will be
38 // deleted when their Adornable dies. Once attached, their memory is owned by the
39 // Adornable (NOT the caller). Do not get fancy with an Adornment's memory;
40 // trying to share one Adornment instance between Adornables or slots is bad.
41 // If you need shared storage, use a RefPointer attachment.
43 // Your Adornment's destructor will be called when its Adornable dies, or when
44 // its slot is replaced (whichever happens sooner). So you CAN get notification
45 // of an object's death by attaching an Adornment with a unique key and putting
46 // code in its destructor.
48 // It is fairly popular for a subclass of Adornable to rename its getAdornment and
49 // adornment methods as operator [], but we won't make that decision for you
55 #include <security_utilities/utilities.h>
56 #include <security_utilities/threading.h>
66 // An Adornment is data "hung" (stored with) an Adornable.
69 friend class Adornable
;
71 typedef const void *Key
;
73 virtual ~Adornment() = 0;
81 // An Adornable can carry Adornments, potentially a different one for each
82 // Key. We provide both a raw interface (dealing in Adornment subclasses),
83 // and an attachment form that just pretends that the Adornable has extra,
84 // dynamically allocated members filed under various keys.
88 Adornable() : mAdornments(NULL
) { }
91 // adornment keys (slots)
92 typedef Adornment::Key Key
;
94 // primitive access, raw form
95 Adornment
*getAdornment(Key key
) const; // NULL if not present
96 void setAdornment(Key key
, Adornment
*ad
); // use NULL to delete
97 Adornment
*swapAdornment(Key key
, Adornment
*ad
); // rotate in/out
99 // typed primitive access. Ad must be a unique subclass of Adornment
101 Ad
*getAdornment(Key key
) const
102 { return safe_cast
<Ad
*>(getAdornment(key
)); }
105 Ad
*swapAdornment(Key key
, Ad
*ad
)
106 { return safe_cast
<Ad
*>(swapAdornment(key
, ad
)); }
108 // inquiries for the Adornable itself
109 bool empty() const { return !mAdornments
|| mAdornments
->empty(); }
110 unsigned int size() const { return mAdornments
? (unsigned int)mAdornments
->size() : 0; }
111 void clearAdornments();
114 // Adornment ref interface. Will return an (optionally constructed) Adornment &.
115 template <class T
> T
&adornment(Key key
);
116 template <class T
, class Arg1
> T
&adornment(Key key
, Arg1
&arg1
);
117 template <class T
, class Arg1
, class Arg2
> T
&adornment(Key key
, Arg1
&arg1
, Arg2
&arg2
);
118 template <class T
, class Arg1
, class Arg2
, class Arg3
> T
&adornment(Key key
, Arg1
&arg1
, Arg2
&arg2
, Arg3
&arg3
);
120 // attached-value interface
121 template <class T
> T
&attachment(Key key
);
122 template <class T
, class Arg1
> T
&attachment(Key key
, Arg1 arg1
);
125 Adornment
*&adornmentSlot(Key key
);
127 template <class Type
>
128 struct Attachment
: public Adornment
{
130 template <class Arg1
> Attachment(Arg1 arg
) : mValue(arg
) { }
135 typedef std::map
<Key
, Adornment
*> AdornmentMap
;
136 AdornmentMap
*mAdornments
;
141 // Out-of-line implementations
143 template <class T
> T
&
144 Adornable::adornment(Key key
)
146 Adornment
*&slot
= adornmentSlot(key
);
149 return dynamic_cast<T
&>(*slot
);
152 template <class T
, class Arg1
> T
&
153 Adornable::adornment(Key key
, Arg1
&arg1
)
155 Adornment
*&slot
= adornmentSlot(key
);
158 return dynamic_cast<T
&>(*slot
);
161 template <class T
, class Arg1
, class Arg2
> T
&
162 Adornable::adornment(Key key
, Arg1
&arg1
, Arg2
&arg2
)
164 Adornment
*&slot
= adornmentSlot(key
);
166 slot
= new T(arg1
, arg2
);
167 return dynamic_cast<T
&>(*slot
);
170 template <class T
, class Arg1
, class Arg2
, class Arg3
> T
&
171 Adornable::adornment(Key key
, Arg1
&arg1
, Arg2
&arg2
, Arg3
&arg3
)
173 Adornment
*&slot
= adornmentSlot(key
);
175 slot
= new T(arg1
, arg2
, arg3
);
176 return dynamic_cast<T
&>(*slot
);
180 T
&Adornable::attachment(Key key
)
182 typedef Attachment
<T
> Attach
;
183 Adornment
*&slot
= adornmentSlot(key
);
186 return safe_cast
<Attach
*>(slot
)->mValue
;
189 template <class T
, class Arg1
>
190 T
&Adornable::attachment(Key key
, Arg1 arg1
)
192 typedef Attachment
<T
> Attach
;
193 Adornment
*&slot
= adornmentSlot(key
);
195 slot
= new Attach(arg1
);
196 return safe_cast
<Attach
*>(slot
)->mValue
;
200 } // end namespace Security
202 #endif //_H_ADORNMENTS