2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // cssmdata.h -- Manager different CssmData types
22 #ifndef _H_CDSA_UTILITIES_CSSMDATA
23 #define _H_CDSA_UTILITIES_CSSMDATA
25 #include <Security/utilities.h>
26 #include <Security/cssmalloc.h>
27 #include <Security/refcount.h>
29 #ifdef _CPP_CDSA_UTILITIES_CSSMDATA
37 // The following pseudo-code describes what (at minimum) is required for a class
38 // to be a "PseudoData". PseudoData arguments are used in templates.
41 // void *data() const ...
42 // size_t length() const ...
43 // operator const CssmData &() const ...
46 // All this can be satisfied, of course, by inheriting form CssmData.
51 // A common virtual parent for CssmData-like objects that actively manage the
52 // allocation status of their data blob. Note that this is about allocating
53 // the data(), not the CssmData structure itself.
54 // The ManagedData layer provides for little active memory management, since
55 // the underlying strategies are potentially very disparate. It does however
56 // have a well defined interface for *yielding up* its data for copying or transfer.
58 class CssmManagedData
{
60 CssmManagedData(CssmAllocator
&alloc
) : allocator(alloc
) { }
61 virtual ~CssmManagedData();
63 CssmAllocator
&allocator
;
65 virtual operator const CssmData
& () const { return get(); }
66 template <class T
> T
*data() const { return reinterpret_cast<T
*>(data()); }
67 void *data() const { return get().data(); }
68 size_t length() const { return get().length(); }
70 virtual CssmData
&get() const throw() = 0; // get shared copy, no ownership change
71 virtual CssmData
release() = 0; // give up copy, ownership is transferred
72 virtual void reset() = 0; // give up copy, data is discarded
77 // A CssmOwnedData is a CssmManagedData that unilaterally owns its data storage.
78 // It has its CssmData object provided during construction.
80 class CssmOwnedData
: public CssmManagedData
{
82 CssmOwnedData(CssmAllocator
&alloc
, CssmData
&mine
) : CssmManagedData(alloc
), referent(mine
) { }
84 CssmOwnedData(CssmAllocator
&alloc
, CSSM_DATA
&mine
)
85 : CssmManagedData(alloc
), referent(CssmData::overlay(mine
)) { referent
.clear(); }
88 // Basic retrievals (this echoes features of CssmData)
90 operator void * () const { return referent
; }
91 operator char * () const { return referent
; }
92 operator signed char * () const { return referent
; }
93 operator unsigned char * () const { return referent
; }
95 operator bool () const { return referent
; }
96 bool operator ! () const { return !referent
; }
98 size_t length() const { return referent
.length(); }
104 void *malloc(size_t len
)
106 // pseudo-atomic reallocation semantics
107 CssmAutoPtr
<uint8
> alloc(allocator
, allocator
.malloc
<uint8
>(len
));
109 return referent
= CssmData(alloc
.release(), len
);
112 void *realloc(size_t newLen
)
114 // CssmAllocator::realloc() should be pseudo-atomic (i.e. throw on error)
115 return referent
= CssmData(allocator
.realloc
<uint8
>(referent
.data(), newLen
), newLen
);
118 void length(size_t len
) { realloc(len
); }
122 // Manipulate existing data
124 void *append(const void *addData
, size_t addLength
)
126 size_t oldLength
= length();
127 realloc(oldLength
+ addLength
);
128 return memcpy(referent
.at(oldLength
), addData
, addLength
);
131 void *append(const CssmData
&data
)
132 { return append(data
.data(), data
.length()); }
135 // set() replaces current data with new, taking over ownership to the extent possible.
138 void set(T
*data
, size_t length
)
140 // assume that data was allocated by our allocator -- we can't be sure
142 referent
= CssmData(data
, length
);
145 void set(CssmManagedData
&source
);
146 void set(const CSSM_DATA
&source
) { set(source
.Data
, source
.Length
); }
147 // NOTE: General template set() cannot be used because all subclasses of CssmManagedData
148 // need to receive the special handling above. Use set(*.data(), *.length()) instead.
152 // copy() replaces current data with new, making a copy and leaving
153 // the source intact.
156 void copy(const T
*data
, size_t length
)
158 // don't leave any open windows for Mr. Murphy
159 CssmAutoPtr
<void> newData(allocator
, memcpy(allocator
.malloc(length
), data
, length
));
161 referent
= CssmData(newData
.release(), length
);
164 void copy(const CssmData
&source
)
165 { if (&source
!= &referent
) copy(source
.data(), source
.length()); }
166 void copy(const CSSM_DATA
&source
)
167 { if (&source
!= &referent
) copy(source
.Data
, source
.Length
); }
168 void copy(CssmManagedData
&source
) { copy(source
.get()); }
169 template <class Data
>
170 void copy(const Data
&source
) { copy(source
.data(), source
.length()); }
174 // Assignment conservatively uses copy if allocator unknown, set if known
176 void operator = (CssmManagedData
&source
) { set(source
); }
177 void operator = (CssmOwnedData
&source
) { set(source
); }
178 void operator = (const CSSM_DATA
&source
) { copy(source
); }
180 CssmData
&get() const throw() { return referent
; }
188 // A CssmAutoData is a CssmOwnedData that includes its CssmData object.
189 // This is the very simple case: The object includes ownership, data object,
192 class CssmAutoData
: public CssmOwnedData
{
194 CssmAutoData(CssmAllocator
&alloc
) : CssmOwnedData(alloc
, mData
) { }
196 template <class Data
>
197 CssmAutoData(CssmAllocator
&alloc
, const Data
&source
) : CssmOwnedData(alloc
, mData
)
200 explicit CssmAutoData(CssmManagedData
&source
) : CssmOwnedData(source
.allocator
, mData
)
203 CssmAutoData(CssmAllocator
&alloc
, const void *data
, size_t length
)
204 : CssmOwnedData(alloc
, mData
) { copy(data
, length
); }
206 ~CssmAutoData() { allocator
.free(mData
); }
211 // assignment (not usefully inherited)
212 void operator = (CssmManagedData
&source
) { set(source
); }
213 void operator = (CssmOwnedData
&source
) { set(source
); }
214 void operator = (CssmAutoData
&source
) { set(source
); }
215 template <class Data
>
216 void operator = (const Data
&source
) { copy(source
); }
224 // A CssmRemoteData is a CssmOwnedData that uses an external CssmData object.
225 // Its release operation clears an internal ownership flag but does not clear
226 // the CssmData values so they can be used to return values to an outside scope.
228 class CssmRemoteData
: public CssmOwnedData
{
230 CssmRemoteData(CssmAllocator
&alloc
, CssmData
&mine
)
231 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
233 CssmRemoteData(CssmAllocator
&alloc
, CSSM_DATA
&mine
)
234 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
237 { if (iOwnTheData
) allocator
.free(referent
); }
242 // assignment (not usefully inherited)
243 void operator = (CssmManagedData
&source
) { set(source
); }
244 void operator = (CssmOwnedData
&source
) { set(source
); }
245 void operator = (CssmAutoData
&source
) { set(source
); }
246 template <class Data
>
247 void operator = (const Data
&source
) { copy(source
); }
257 // Used by functions that take a CssmData and would like to allow it to be
258 // initialized with a static string, int or other basic type. The function *must*
259 // copy the Data of the CssmPolyData when doing so if it is to be used
260 // after the function returns. (For example by creating a CssmDataContainer from it).
261 class CssmPolyData
: public CssmData
{
263 uint8
*set(const T
&it
)
264 { return const_cast<uint8
*>(reinterpret_cast<const uint8
*>(&it
)); }
266 template <class char_T
>
267 CssmPolyData(const char_T
*s
) : CssmData(const_cast<char_T
*>(s
), strlen(s
)) {}
268 CssmPolyData(const string
&s
) : CssmData(const_cast<char *>(s
.c_str()), s
.size()) {}
269 CssmPolyData(const CSSM_DATA
&data
) : CssmData(data
.Data
, data
.Length
) {}
271 // Don't use a template constructor (for T &) here - it would eat way too much
272 CssmPolyData(const bool &t
) : CssmData(set(t
), sizeof(t
)) { }
273 CssmPolyData(const uint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
274 CssmPolyData(const sint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
275 CssmPolyData(const sint64
&t
) : CssmData(set(t
), sizeof(t
)) { }
276 CssmPolyData(const double &t
) : CssmData(set(t
), sizeof(t
)) { }
279 class CssmDateData
: public CssmData
282 CssmDateData(const CSSM_DATE
&date
);
287 class CssmGuidData
: public CssmData
290 CssmGuidData(const CSSM_GUID
&guid
);
292 char buffer
[Guid::stringRepLength
+ 1];
302 CssmDLPolyData(const CSSM_DATA
&data
, CSSM_DB_ATTRIBUTE_FORMAT format
)
303 : mData(CssmData::overlay(data
)), mFormat(format
) {}
305 // @@@ Don't use assert, but throw an exception.
306 // @@@ Do a size check on mData as well.
308 // @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated.
309 operator const char *() const
311 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_STRING
312 || mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
);
313 return reinterpret_cast<const char *>(mData
.Data
);
315 operator bool() const
317 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_UINT32
|| mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_SINT32
);
318 return *reinterpret_cast<uint32
*>(mData
.Data
);
320 operator uint32() const
322 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_UINT32
);
323 return *reinterpret_cast<uint32
*>(mData
.Data
);
325 operator const uint32
*() const
327 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
);
328 return reinterpret_cast<const uint32
*>(mData
.Data
);
330 operator sint32() const
332 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_SINT32
);
333 return *reinterpret_cast<sint32
*>(mData
.Data
);
335 operator double() const
337 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_REAL
);
338 return *reinterpret_cast<double *>(mData
.Data
);
340 operator CSSM_DATE () const;
341 operator Guid () const;
342 operator const CssmData
&() const
348 const CssmData
&mData
;
349 CSSM_DB_ATTRIBUTE_FORMAT mFormat
;
354 // Non POD refcounted CssmData wrapper that own the data it refers to.
356 class CssmDataContainer
: public CssmData
, public RefCount
359 CssmDataContainer(CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
360 CssmData(), mAllocator(inAllocator
) {}
362 CssmDataContainer(const T
*data
, size_t length
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
363 CssmData(inAllocator
.malloc(length
), length
), mAllocator(inAllocator
)
364 { if (length
) ::memcpy(Data
, data
, length
); }
365 void clear() { if (Data
) { mAllocator
.free(Data
); Data
= NULL
; Length
= 0; } }
366 ~CssmDataContainer() { if (Data
) mAllocator
.free(Data
); }
367 void append(const CssmPolyData
&data
)
369 uint32 newLength
= Length
+ data
.Length
;
370 Data
= reinterpret_cast<uint8
*>(mAllocator
.realloc(Data
, newLength
));
371 memcpy(Data
+ Length
, data
.Data
, data
.Length
);
374 CssmDataContainer(const CssmDataContainer
&other
)
375 : mAllocator(other
.mAllocator
)
377 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
378 memcpy(Data
, other
.Data
, other
.Length
);
379 Length
= other
.Length
;
381 CssmDataContainer
& operator = (const CSSM_DATA
&other
)
384 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
385 memcpy(Data
, other
.Data
, other
.Length
);
386 Length
= other
.Length
;
391 CssmAllocator
&mAllocator
;
394 operator CssmDataContainer
* () const; // prohibit conversion-to-my-pointer
398 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
400 typedef CssmDataContainer CssmOidContainer
;
402 template <class Container
>
403 class CssmBuffer
: public RefPointer
<Container
>
406 CssmBuffer() : RefPointer
<Container
>(new Container()) {} // XXX This should may just set ptr to NULL.
408 CssmBuffer(const T
*data
, size_t length
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
409 RefPointer
<Container
>(new Container(data
, length
, inAllocator
)) {}
410 CssmBuffer(const CSSM_DATA
&data
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
411 RefPointer
<Container
>(new Container(data
.Data
, data
.Length
, inAllocator
)) {}
412 CssmBuffer(const CssmBuffer
& other
) : RefPointer
<Container
>(other
) {}
413 CssmBuffer(Container
*p
) : RefPointer
<Container
>(p
) {}
414 bool CssmBuffer::operator < (const CssmBuffer
&other
) const { return (**this) < (*other
); }
417 } // end namespace Security
423 #endif // _H_CDSA_UTILITIES_CSSMDATA