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
)) { }
41 StringData(const std::string
&s
) : CssmData(const_cast<char *>(s
.c_str()), s
.size()) { }
46 // A CssmData bundled up with a data buffer it refers to
48 template <size_t size
>
49 struct DataBuffer
: public CssmData
{
50 unsigned char buffer
[size
];
51 DataBuffer() : CssmData(buffer
, size
) { }
56 // Comparing CssmDatas for equality.
57 // Note: No ordering is established here.
58 // Both CSSM_DATAs have to exist.
60 bool operator == (const CSSM_DATA
&d1
, const CSSM_DATA
&d2
);
61 inline bool operator != (const CSSM_DATA
&d1
, const CSSM_DATA
&d2
)
62 { return !(d1
== d2
); }
66 // The following pseudo-code describes what (at minimum) is required for a class
67 // to be a "PseudoData". PseudoData arguments are used in templates.
70 // void *data() const ...
71 // size_t length() const ...
72 // operator const CssmData &() const ...
75 // All this can be satisfied, of course, by inheriting from CssmData.
80 // A common virtual parent for CssmData-like objects that actively manage the
81 // allocation status of their data blob. Note that this is about allocating
82 // the data(), not the CssmData structure itself.
83 // The ManagedData layer provides for little active memory management, since
84 // the underlying strategies are potentially very disparate. It does however
85 // have a well defined interface for *yielding up* its data for copying or transfer.
87 class CssmManagedData
{
89 CssmManagedData(CssmAllocator
&alloc
) : allocator(alloc
) { }
90 virtual ~CssmManagedData();
92 CssmAllocator
&allocator
;
94 virtual operator const CssmData
& () const { return get(); }
95 template <class T
> T
*data() const { return reinterpret_cast<T
*>(data()); }
96 void *data() const { return get().data(); }
97 size_t length() const { return get().length(); }
99 virtual CssmData
&get() const throw() = 0; // get shared copy, no ownership change
100 virtual CssmData
release() = 0; // give up copy, ownership is transferred
101 virtual void reset() = 0; // give up copy, data is discarded
105 inline bool operator == (const CssmManagedData
&d1
, const CssmData
&d2
)
106 { return d1
.get() == d2
; }
108 inline bool operator == (const CssmData
&d1
, const CssmManagedData
&d2
)
109 { return d1
== d2
.get(); }
111 inline bool operator == (const CssmManagedData
&d1
, const CssmManagedData
&d2
)
112 { return d1
.get() == d2
.get(); }
114 inline bool operator != (const CssmManagedData
&d1
, const CssmData
&d2
)
115 { return d1
.get() != d2
; }
117 inline bool operator != (const CssmData
&d1
, const CssmManagedData
&d2
)
118 { return d1
!= d2
.get(); }
120 inline bool operator != (const CssmManagedData
&d1
, const CssmManagedData
&d2
)
121 { return d1
.get() != d2
.get(); }
125 // A CssmOwnedData is a CssmManagedData that unilaterally owns its data storage.
126 // It has its CssmData object provided during construction.
128 class CssmOwnedData
: public CssmManagedData
{
130 CssmOwnedData(CssmAllocator
&alloc
, CssmData
&mine
) : CssmManagedData(alloc
), referent(mine
) { }
132 CssmOwnedData(CssmAllocator
&alloc
, CSSM_DATA
&mine
)
133 : CssmManagedData(alloc
), referent(CssmData::overlay(mine
)) { referent
.clear(); }
136 // Basic retrievals (this echoes features of CssmData)
138 operator void * () const { return referent
; }
139 operator char * () const { return referent
; }
140 operator signed char * () const { return referent
; }
141 operator unsigned char * () const { return referent
; }
143 operator bool () const { return referent
; }
144 bool operator ! () const { return !referent
; }
146 size_t length() const { return referent
.length(); }
152 void *malloc(size_t len
)
154 // pseudo-atomic reallocation semantics
155 CssmAutoPtr
<uint8
> alloc(allocator
, allocator
.malloc
<uint8
>(len
));
157 return referent
= CssmData(alloc
.release(), len
);
160 void *realloc(size_t newLen
)
162 // CssmAllocator::realloc() should be pseudo-atomic (i.e. throw on error)
163 return referent
= CssmData(allocator
.realloc
<uint8
>(referent
.data(), newLen
), newLen
);
166 void length(size_t len
) { realloc(len
); }
170 // Manipulate existing data
172 void *append(const void *addData
, size_t addLength
)
174 size_t oldLength
= length();
175 realloc(oldLength
+ addLength
);
176 return memcpy(referent
.at(oldLength
), addData
, addLength
);
179 void *append(const CssmData
&data
)
180 { return append(data
.data(), data
.length()); }
183 // set() replaces current data with new, taking over ownership to the extent possible.
186 void set(T
*data
, size_t length
)
188 // assume that data was allocated by our allocator -- we can't be sure
190 referent
= CssmData(data
, length
);
193 void set(CssmManagedData
&source
);
194 void set(const CSSM_DATA
&source
) { set(source
.Data
, source
.Length
); }
195 // NOTE: General template set() cannot be used because all subclasses of CssmManagedData
196 // need to receive the special handling above. Use set(*.data(), *.length()) instead.
200 // copy() replaces current data with new, making a copy and leaving
201 // the source intact.
204 void copy(const T
*data
, size_t length
)
206 // don't leave any open windows for Mr. Murphy
207 CssmAutoPtr
<void> newData(allocator
, memcpy(allocator
.malloc(length
), data
, length
));
209 referent
= CssmData(newData
.release(), length
);
212 void copy(const CssmData
&source
)
213 { if (&source
!= &referent
) copy(source
.data(), source
.length()); }
214 void copy(const CSSM_DATA
&source
)
215 { if (&source
!= &referent
) copy(source
.Data
, source
.Length
); }
216 void copy(CssmManagedData
&source
) { copy(source
.get()); }
217 template <class Data
>
218 void copy(const Data
&source
) { copy(source
.data(), source
.length()); }
222 // Assignment conservatively uses copy if allocator unknown, set if known
224 void operator = (CssmManagedData
&source
) { set(source
); }
225 void operator = (CssmOwnedData
&source
) { set(source
); }
226 void operator = (const CSSM_DATA
&source
) { copy(source
); }
228 CssmData
&get() const throw() { return referent
; }
236 // A CssmAutoData is a CssmOwnedData that includes its CssmData object.
237 // This is the very simple case: The object includes ownership, data object,
240 class CssmAutoData
: public CssmOwnedData
{
242 CssmAutoData(CssmAllocator
&alloc
) : CssmOwnedData(alloc
, mData
) { }
244 template <class Data
>
245 CssmAutoData(CssmAllocator
&alloc
, const Data
&source
) : CssmOwnedData(alloc
, mData
)
248 CssmAutoData(CssmAutoData
&source
) : CssmOwnedData(source
.allocator
, mData
)
251 explicit CssmAutoData(CssmManagedData
&source
) : CssmOwnedData(source
.allocator
, mData
)
254 CssmAutoData(CssmAllocator
&alloc
, const void *data
, size_t length
)
255 : CssmOwnedData(alloc
, mData
) { copy(data
, length
); }
257 ~CssmAutoData() { allocator
.free(mData
); }
262 // assignment (not usefully inherited)
263 void operator = (CssmManagedData
&source
) { set(source
); }
264 void operator = (CssmOwnedData
&source
) { set(source
); }
265 void operator = (CssmAutoData
&source
) { set(source
); }
266 template <class Data
>
267 void operator = (const Data
&source
) { copy(source
); }
275 // A CssmRemoteData is a CssmOwnedData that uses an external CssmData object.
276 // Its release operation clears an internal ownership flag but does not clear
277 // the CssmData values so they can be used to return values to an outside scope.
279 class CssmRemoteData
: public CssmOwnedData
{
281 CssmRemoteData(CssmAllocator
&alloc
, CssmData
&mine
)
282 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
284 CssmRemoteData(CssmAllocator
&alloc
, CSSM_DATA
&mine
)
285 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
288 { if (iOwnTheData
) allocator
.free(referent
); }
293 // assignment (not usefully inherited)
294 void operator = (CssmManagedData
&source
) { set(source
); }
295 void operator = (CssmOwnedData
&source
) { set(source
); }
296 void operator = (CssmAutoData
&source
) { set(source
); }
297 template <class Data
>
298 void operator = (const Data
&source
) { copy(source
); }
308 // Used by functions that take a CssmData and would like to allow it to be
309 // initialized with a static string, int or other basic type. The function *must*
310 // copy the Data of the CssmPolyData when doing so if it is to be used
311 // after the function returns. (For example by creating a CssmDataContainer from it).
312 class CssmPolyData
: public CssmData
{
314 uint8
*set(const T
&it
)
315 { return const_cast<uint8
*>(reinterpret_cast<const uint8
*>(&it
)); }
317 template <class char_T
>
318 CssmPolyData(const char_T
*s
) : CssmData(const_cast<char_T
*>(s
), strlen(s
)) {}
319 CssmPolyData(const string
&s
) : CssmData(const_cast<char *>(s
.c_str()), s
.size()) {}
320 CssmPolyData(const CSSM_DATA
&data
) : CssmData(data
.Data
, data
.Length
) {}
322 // Don't use a template constructor (for T &) here - it would eat way too much
323 CssmPolyData(const bool &t
) : CssmData(set(t
), sizeof(t
)) { }
324 CssmPolyData(const uint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
325 CssmPolyData(const sint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
326 CssmPolyData(const sint64
&t
) : CssmData(set(t
), sizeof(t
)) { }
327 CssmPolyData(const double &t
) : CssmData(set(t
), sizeof(t
)) { }
328 CssmPolyData(const StringPtr s
) : CssmData (reinterpret_cast<char*>(s
+ 1), uint32 (s
[0])) {}
331 class CssmDateData
: public CssmData
334 CssmDateData(const CSSM_DATE
&date
);
339 class CssmGuidData
: public CssmData
342 CssmGuidData(const CSSM_GUID
&guid
);
344 char buffer
[Guid::stringRepLength
+ 1];
354 CssmDLPolyData(const CSSM_DATA
&data
, CSSM_DB_ATTRIBUTE_FORMAT format
)
355 : mData(CssmData::overlay(data
)), mFormat(format
) {}
357 // @@@ Don't use assert, but throw an exception.
358 // @@@ Do a size check on mData as well.
360 // @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated.
361 operator const char *() const
363 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_STRING
364 || mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
);
365 return reinterpret_cast<const char *>(mData
.Data
);
367 operator bool() const
369 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_UINT32
|| mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_SINT32
);
370 return *reinterpret_cast<uint32
*>(mData
.Data
);
372 operator uint32() const
374 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_UINT32
);
375 return *reinterpret_cast<uint32
*>(mData
.Data
);
377 operator const uint32
*() const
379 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
);
380 return reinterpret_cast<const uint32
*>(mData
.Data
);
382 operator sint32() const
384 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_SINT32
);
385 return *reinterpret_cast<sint32
*>(mData
.Data
);
387 operator double() const
389 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_REAL
);
390 return *reinterpret_cast<double *>(mData
.Data
);
392 operator CSSM_DATE () const;
393 operator Guid () const;
394 operator const CssmData
&() const
400 const CssmData
&mData
;
401 CSSM_DB_ATTRIBUTE_FORMAT mFormat
;
406 // Non POD refcounted CssmData wrapper that own the data it refers to.
408 class CssmDataContainer
: public CssmData
, public RefCount
411 CssmDataContainer(CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
412 CssmData(), mAllocator(inAllocator
) {}
414 CssmDataContainer(const T
*data
, size_t length
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
415 CssmData(inAllocator
.malloc(length
), length
), mAllocator(inAllocator
)
416 { if (length
) ::memcpy(Data
, data
, length
); }
417 void clear() { if (Data
) { mAllocator
.free(Data
); Data
= NULL
; Length
= 0; } }
418 void invalidate () {Data
= NULL
; Length
= 0;}
419 ~CssmDataContainer() { if (Data
) mAllocator
.free(Data
); }
420 void append(const CssmPolyData
&data
)
422 uint32 newLength
= Length
+ data
.Length
;
423 Data
= reinterpret_cast<uint8
*>(mAllocator
.realloc(Data
, newLength
));
424 memcpy(Data
+ Length
, data
.Data
, data
.Length
);
427 CssmDataContainer(const CssmDataContainer
&other
)
428 : mAllocator(other
.mAllocator
)
430 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
431 memcpy(Data
, other
.Data
, other
.Length
);
432 Length
= other
.Length
;
434 CssmDataContainer
& operator = (const CSSM_DATA
&other
)
437 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
438 memcpy(Data
, other
.Data
, other
.Length
);
439 Length
= other
.Length
;
444 CssmAllocator
&mAllocator
;
447 operator CssmDataContainer
* () const; // prohibit conversion-to-my-pointer
451 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
453 typedef CssmDataContainer CssmOidContainer
;
455 template <class Container
>
456 class CssmBuffer
: public RefPointer
<Container
>
459 CssmBuffer() : RefPointer
<Container
>(new Container()) {} // XXX This should may just set ptr to NULL.
461 CssmBuffer(const T
*data
, size_t length
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
462 RefPointer
<Container
>(new Container(data
, length
, inAllocator
)) {}
463 CssmBuffer(const CSSM_DATA
&data
, CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
464 RefPointer
<Container
>(new Container(data
.Data
, data
.Length
, inAllocator
)) {}
465 CssmBuffer(const CssmBuffer
& other
) : RefPointer
<Container
>(other
) {}
466 CssmBuffer(Container
*p
) : RefPointer
<Container
>(p
) {}
467 bool CssmBuffer::operator < (const CssmBuffer
&other
) const { return (**this) < (*other
); }
471 } // end namespace Security
473 #endif // _H_CDSA_UTILITIES_CSSMDATA