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>
34 // A convenient way to make a CssmData from a (const) string.
35 // Note that the underlying string is not memory-managed, so it
36 // should either be static or of sufficient (immutable) lifetime.
38 class StringData
: public CssmData
{
40 StringData(const char *s
) : CssmData(const_cast<char *>(s
), strlen(s
)) { }
45 // A CssmData bundled up with a data buffer it refers to
47 template <size_t size
>
48 struct DataBuffer
: public CssmData
{
49 unsigned char buffer
[size
];
50 DataBuffer() : CssmData(buffer
, size
) { }
55 // Comparing CssmDatas for equality.
56 // Note: No ordering is established here.
57 // Both CSSM_DATAs have to exist.
59 bool operator == (const CSSM_DATA
&d1
, const CSSM_DATA
&d2
);
60 inline bool operator != (const CSSM_DATA
&d1
, const CSSM_DATA
&d2
)
61 { return !(d1
== d2
); }
65 // The following pseudo-code describes what (at minimum) is required for a class
66 // to be a "PseudoData". PseudoData arguments are used in templates.
69 // void *data() const ...
70 // size_t length() const ...
71 // operator const CssmData &() const ...
74 // All this can be satisfied, of course, by inheriting from CssmData.
79 // A common virtual parent for CssmData-like objects that actively manage the
80 // allocation status of their data blob. Note that this is about allocating
81 // the data(), not the CssmData structure itself.
82 // The ManagedData layer provides for little active memory management, since
83 // the underlying strategies are potentially very disparate. It does however
84 // have a well defined interface for *yielding up* its data for copying or transfer.
86 class CssmManagedData
{
88 CssmManagedData(CssmAllocator
&alloc
) : allocator(alloc
) { }
89 virtual ~CssmManagedData();
91 CssmAllocator
&allocator
;
93 virtual operator const CssmData
& () const { return get(); }
94 template <class T
> T
*data() const { return reinterpret_cast<T
*>(data()); }
95 void *data() const { return get().data(); }
96 size_t length() const { return get().length(); }
98 virtual CssmData
&get() const throw() = 0; // get shared copy, no ownership change
99 virtual CssmData
release() = 0; // give up copy, ownership is transferred
100 virtual void reset() = 0; // give up copy, data is discarded
105 // A CssmOwnedData is a CssmManagedData that unilaterally owns its data storage.
106 // It has its CssmData object provided during construction.
108 class CssmOwnedData
: public CssmManagedData
{
110 CssmOwnedData(CssmAllocator
&alloc
, CssmData
&mine
) : CssmManagedData(alloc
), referent(mine
) { }
112 CssmOwnedData(CssmAllocator
&alloc
, CSSM_DATA
&mine
)
113 : CssmManagedData(alloc
), referent(CssmData::overlay(mine
)) { referent
.clear(); }
116 // Basic retrievals (this echoes features of CssmData)
118 operator void * () const { return referent
; }
119 operator char * () const { return referent
; }
120 operator signed char * () const { return referent
; }
121 operator unsigned char * () const { return referent
; }
123 operator bool () const { return referent
; }
124 bool operator ! () const { return !referent
; }
126 size_t length() const { return referent
.length(); }
132 void *malloc(size_t len
)
134 // pseudo-atomic reallocation semantics
135 CssmAutoPtr
<uint8
> alloc(allocator
, allocator
.malloc
<uint8
>(len
));
137 return referent
= CssmData(alloc
.release(), len
);
140 void *realloc(size_t newLen
)
142 // CssmAllocator::realloc() should be pseudo-atomic (i.e. throw on error)
143 return referent
= CssmData(allocator
.realloc
<uint8
>(referent
.data(), newLen
), newLen
);
146 void length(size_t len
) { realloc(len
); }
150 // Manipulate existing data
152 void *append(const void *addData
, size_t addLength
)
154 size_t oldLength
= length();
155 realloc(oldLength
+ addLength
);
156 return memcpy(referent
.at(oldLength
), addData
, addLength
);
159 void *append(const CssmData
&data
)
160 { return append(data
.data(), data
.length()); }
163 // set() replaces current data with new, taking over ownership to the extent possible.
166 void set(T
*data
, size_t length
)
168 // assume that data was allocated by our allocator -- we can't be sure
170 referent
= CssmData(data
, length
);
173 void set(CssmManagedData
&source
);
174 void set(const CSSM_DATA
&source
) { set(source
.Data
, source
.Length
); }
175 // NOTE: General template set() cannot be used because all subclasses of CssmManagedData
176 // need to receive the special handling above. Use set(*.data(), *.length()) instead.
180 // copy() replaces current data with new, making a copy and leaving
181 // the source intact.
184 void copy(const T
*data
, size_t length
)
186 // don't leave any open windows for Mr. Murphy
187 CssmAutoPtr
<void> newData(allocator
, memcpy(allocator
.malloc(length
), data
, length
));
189 referent
= CssmData(newData
.release(), length
);
192 void copy(const CssmData
&source
)
193 { if (&source
!= &referent
) copy(source
.data(), source
.length()); }
194 void copy(const CSSM_DATA
&source
)
195 { if (&source
!= &referent
) copy(source
.Data
, source
.Length
); }
196 void copy(CssmManagedData
&source
) { copy(source
.get()); }
197 template <class Data
>
198 void copy(const Data
&source
) { copy(source
.data(), source
.length()); }
202 // Assignment conservatively uses copy if allocator unknown, set if known
204 void operator = (CssmManagedData
&source
) { set(source
); }
205 void operator = (CssmOwnedData
&source
) { set(source
); }
206 void operator = (const CSSM_DATA
&source
) { copy(source
); }
208 CssmData
&get() const throw() { return referent
; }
216 // A CssmAutoData is a CssmOwnedData that includes its CssmData object.
217 // This is the very simple case: The object includes ownership, data object,
220 class CssmAutoData
: public CssmOwnedData
{
222 CssmAutoData(CssmAllocator
&alloc
) : CssmOwnedData(alloc
, mData
) { }
224 template <class Data
>
225 CssmAutoData(CssmAllocator
&alloc
, const Data
&source
) : CssmOwnedData(alloc
, mData
)
228 CssmAutoData(CssmAutoData
&source
) : CssmOwnedData(source
.allocator
, mData
)
231 explicit CssmAutoData(CssmManagedData
&source
) : CssmOwnedData(source
.allocator
, mData
)
234 CssmAutoData(CssmAllocator
&alloc
, const void *data
, size_t length
)
235 : CssmOwnedData(alloc
, mData
) { copy(data
, length
); }
237 ~CssmAutoData() { allocator
.free(mData
); }
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
); }
255 // A CssmRemoteData is a CssmOwnedData that uses an external CssmData object.
256 // Its release operation clears an internal ownership flag but does not clear
257 // the CssmData values so they can be used to return values to an outside scope.
259 class CssmRemoteData
: public CssmOwnedData
{
261 CssmRemoteData(CssmAllocator
&alloc
, CssmData
&mine
)
262 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
264 CssmRemoteData(CssmAllocator
&alloc
, CSSM_DATA
&mine
)
265 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
268 { if (iOwnTheData
) allocator
.free(referent
); }
273 // assignment (not usefully inherited)
274 void operator = (CssmManagedData
&source
) { set(source
); }
275 void operator = (CssmOwnedData
&source
) { set(source
); }
276 void operator = (CssmAutoData
&source
) { set(source
); }
277 template <class Data
>
278 void operator = (const Data
&source
) { copy(source
); }
288 // Used by functions that take a CssmData and would like to allow it to be
289 // initialized with a static string, int or other basic type. The function *must*
290 // copy the Data of the CssmPolyData when doing so if it is to be used
291 // after the function returns. (For example by creating a CssmDataContainer from it).
292 class CssmPolyData
: public CssmData
{
294 uint8
*set(const T
&it
)
295 { return const_cast<uint8
*>(reinterpret_cast<const uint8
*>(&it
)); }
297 template <class char_T
>
298 CssmPolyData(const char_T
*s
) : CssmData(const_cast<char_T
*>(s
), strlen(s
)) {}
299 CssmPolyData(const string
&s
) : CssmData(const_cast<char *>(s
.c_str()), s
.size()) {}
300 CssmPolyData(const CSSM_DATA
&data
) : CssmData(data
.Data
, data
.Length
) {}
302 // Don't use a template constructor (for T &) here - it would eat way too much
303 CssmPolyData(const bool &t
) : CssmData(set(t
), sizeof(t
)) { }
304 CssmPolyData(const uint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
305 CssmPolyData(const sint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
306 CssmPolyData(const sint64
&t
) : CssmData(set(t
), sizeof(t
)) { }
307 CssmPolyData(const double &t
) : CssmData(set(t
), sizeof(t
)) { }
308 CssmPolyData(const StringPtr s
) : CssmData (reinterpret_cast<char*>(s
+ 1), uint32 (s
[0])) {}
311 class CssmDateData
: public CssmData
314 CssmDateData(const CSSM_DATE
&date
);
319 class CssmGuidData
: public CssmData
322 CssmGuidData(const CSSM_GUID
&guid
);
324 char buffer
[Guid::stringRepLength
+ 1];
334 CssmDLPolyData(const CSSM_DATA
&data
, CSSM_DB_ATTRIBUTE_FORMAT format
)
335 : mData(CssmData::overlay(data
)), mFormat(format
) {}
337 // @@@ Don't use assert, but throw an exception.
338 // @@@ Do a size check on mData as well.
340 // @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated.
341 operator const char *() const
343 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_STRING
344 || mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
);
345 return reinterpret_cast<const char *>(mData
.Data
);
347 operator bool() const
349 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_UINT32
|| mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_SINT32
);
350 return *reinterpret_cast<uint32
*>(mData
.Data
);
352 operator uint32() const
354 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_UINT32
);
355 return *reinterpret_cast<uint32
*>(mData
.Data
);
357 operator const uint32
*() const
359 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
);
360 return reinterpret_cast<const uint32
*>(mData
.Data
);
362 operator sint32() const
364 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_SINT32
);
365 return *reinterpret_cast<sint32
*>(mData
.Data
);
367 operator double() const
369 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_REAL
);
370 return *reinterpret_cast<double *>(mData
.Data
);
372 operator CSSM_DATE () const;
373 operator Guid () const;
374 operator const CssmData
&() const
380 const CssmData
&mData
;
381 CSSM_DB_ATTRIBUTE_FORMAT mFormat
;
386 // Non POD refcounted CssmData wrapper that own the data it refers to.
388 class CssmDataContainer
: public CssmData
, public RefCount
391 CssmDataContainer(CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
392 CssmData(), mAllocator(inAllocator
) {}
394 CssmDataContainer(const T
*data
, size_t length
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
395 CssmData(inAllocator
.malloc(length
), length
), mAllocator(inAllocator
)
396 { if (length
) ::memcpy(Data
, data
, length
); }
397 void clear() { if (Data
) { mAllocator
.free(Data
); Data
= NULL
; Length
= 0; } }
398 ~CssmDataContainer() { if (Data
) mAllocator
.free(Data
); }
399 void append(const CssmPolyData
&data
)
401 uint32 newLength
= Length
+ data
.Length
;
402 Data
= reinterpret_cast<uint8
*>(mAllocator
.realloc(Data
, newLength
));
403 memcpy(Data
+ Length
, data
.Data
, data
.Length
);
406 CssmDataContainer(const CssmDataContainer
&other
)
407 : mAllocator(other
.mAllocator
)
409 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
410 memcpy(Data
, other
.Data
, other
.Length
);
411 Length
= other
.Length
;
413 CssmDataContainer
& operator = (const CSSM_DATA
&other
)
416 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
417 memcpy(Data
, other
.Data
, other
.Length
);
418 Length
= other
.Length
;
423 CssmAllocator
&mAllocator
;
426 operator CssmDataContainer
* () const; // prohibit conversion-to-my-pointer
430 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
432 typedef CssmDataContainer CssmOidContainer
;
434 template <class Container
>
435 class CssmBuffer
: public RefPointer
<Container
>
438 CssmBuffer() : RefPointer
<Container
>(new Container()) {} // XXX This should may just set ptr to NULL.
440 CssmBuffer(const T
*data
, size_t length
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
441 RefPointer
<Container
>(new Container(data
, length
, inAllocator
)) {}
442 CssmBuffer(const CSSM_DATA
&data
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
443 RefPointer
<Container
>(new Container(data
.Data
, data
.Length
, inAllocator
)) {}
444 CssmBuffer(const CssmBuffer
& other
) : RefPointer
<Container
>(other
) {}
445 CssmBuffer(Container
*p
) : RefPointer
<Container
>(p
) {}
446 bool CssmBuffer::operator < (const CssmBuffer
&other
) const { return (**this) < (*other
); }
450 } // end namespace Security
452 #endif // _H_CDSA_UTILITIES_CSSMDATA