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.
25 #include <Security/cssm.h>
26 #include <Security/utility_config.h>
41 // Elementary debugging support.
42 // #include <debugging.h> for more debugging facilities.
46 # define safe_cast static_cast
47 # define safer_cast static_cast
49 # define IFDEBUG(it) /* do nothing */
50 # define IFNDEBUG(it) it
54 template <class Derived
, class Base
>
55 inline Derived
safer_cast(Base
&base
)
57 return dynamic_cast<Derived
>(base
);
60 template <class Derived
, class Base
>
61 inline Derived
safe_cast(Base
*base
)
64 return NULL
; // okay to cast NULL to NULL
65 Derived p
= dynamic_cast<Derived
>(base
);
70 # define IFDEBUG(it) it
71 # define IFNDEBUG(it) /* do nothing */
77 // Place this into your class definition if you don't want it to be copyable
78 // or asignable. This will not prohibit allocation on the stack or in static
79 // memory, but it will make anything derived from it, and anything containing
80 // it, fixed-once-created. A proper object, I suppose.
82 #define NOCOPY(Type) private: Type(const Type &); void operator = (const Type &);
86 // Exception hierarchy
88 class CssmCommonError
: public std::exception
{
91 CssmCommonError(const CssmCommonError
&source
);
93 virtual ~CssmCommonError() throw ();
95 virtual CSSM_RETURN
cssmError() const = 0;
96 virtual CSSM_RETURN
cssmError(CSSM_RETURN base
) const;
97 virtual OSStatus
osStatus() const;
100 virtual void debugDiagnose(const void *id
) const; // used internally for debug logging
103 IFDEBUG(mutable bool mCarrier
); // primary carrier of exception flow
106 class CssmError
: public CssmCommonError
{
108 CssmError(CSSM_RETURN err
);
110 const CSSM_RETURN error
;
111 virtual CSSM_RETURN
cssmError() const;
112 virtual OSStatus
osStatus() const;
113 virtual const char *what () const throw ();
115 static CSSM_RETURN
merge(CSSM_RETURN error
, CSSM_RETURN base
);
117 static void check(CSSM_RETURN error
) { if (error
!= CSSM_OK
) throwMe(error
); }
118 static void throwMe(CSSM_RETURN error
) __attribute__((noreturn
));
121 class UnixError
: public CssmCommonError
{
127 virtual CSSM_RETURN
cssmError() const;
128 virtual OSStatus
osStatus() const;
129 virtual const char *what () const throw ();
131 static void check(int result
) { if (result
== -1) throwMe(); }
132 static void throwMe(int err
= errno
) __attribute__((noreturn
));
134 // @@@ This is a hack for the Network protocol state machine
135 static UnixError
make(int err
= errno
);
138 IFDEBUG(void debugDiagnose(const void *id
) const);
141 class MacOSError
: public CssmCommonError
{
146 virtual CSSM_RETURN
cssmError() const;
147 virtual OSStatus
osStatus() const;
148 virtual const char *what () const throw ();
150 static void check(OSStatus status
) { if (status
!= noErr
) throwMe(status
); }
151 static void throwMe(int err
) __attribute__((noreturn
));
156 // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions.
159 // ... your C++ code here ...
160 // END_API(base) // returns CSSM_RETURN on exception; complete it to 'base' (DL, etc.) class;
161 // // returns CSSM_OK on fall-through
162 // END_API0 // completely ignores exceptions; falls through in all cases
163 // END_API1(bad) // return (bad) on exception; fall through on success
165 #define BEGIN_API try {
166 #define END_API(base) } \
167 catch (const CssmCommonError &err) { return err.cssmError(CSSM_ ## base ## _BASE_ERROR); } \
168 catch (const std::bad_alloc &) { return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
169 catch (...) { return CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
171 #define END_API0 } catch (...) { return; }
172 #define END_API1(bad) } catch (...) { return bad; }
176 // Helpers for memory pointer validation
179 inline T
&Required(T
*ptr
, CSSM_RETURN err
= CSSM_ERRCODE_INVALID_POINTER
)
182 CssmError::throwMe(err
);
188 // Tools to build POD wrapper classes
190 template <class Wrapper
, class POD
>
191 class PodWrapper
: public POD
{
194 static Wrapper
* &overlayVar(POD
* &data
)
195 { return reinterpret_cast<Wrapper
* &>(data
); }
196 static const Wrapper
* &overlayVar(const POD
* &data
)
197 { return reinterpret_cast<const Wrapper
* &>(data
); }
199 static Wrapper
*overlay(POD
*data
)
200 { return static_cast<Wrapper
*>(data
); }
201 static const Wrapper
*overlay(const POD
*data
)
202 { return static_cast<const Wrapper
*>(data
); }
203 static Wrapper
&overlay(POD
&data
)
204 { return static_cast<Wrapper
&>(data
); }
205 static const Wrapper
&overlay(const POD
&data
)
206 { return static_cast<const Wrapper
&>(data
); }
208 // optional/required forms
209 static Wrapper
&required(POD
*data
)
210 { return overlay(Required(data
)); }
211 static const Wrapper
&required(const POD
*data
)
212 { return overlay(Required(data
)); }
213 static Wrapper
*optional(POD
*data
)
214 { return overlay(data
); }
215 static const Wrapper
*optional(const POD
*data
)
216 { return overlay(data
); }
218 // general helpers for all PodWrappers
220 { memset(static_cast<POD
*>(this), 0, sizeof(POD
)); }
225 // Template builder support
233 struct Nonconst
<const U
> {
239 // User-friendly GUIDs
241 class Guid
: public PodWrapper
<Guid
, CSSM_GUID
> {
243 Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
244 Guid(const CSSM_GUID
&rGuid
) { memcpy(this, &rGuid
, sizeof(*this)); }
246 Guid
&operator = (const CSSM_GUID
&rGuid
)
247 { memcpy(this, &rGuid
, sizeof(CSSM_GUID
)); return *this; }
249 bool operator == (const CSSM_GUID
&other
) const
250 { return (this == &other
) || !memcmp(this, &other
, sizeof(CSSM_GUID
)); }
251 bool operator != (const CSSM_GUID
&other
) const
252 { return (this != &other
) && memcmp(this, &other
, sizeof(CSSM_GUID
)); }
253 bool operator < (const CSSM_GUID
&other
) const
254 { return memcmp(this, &other
, sizeof(CSSM_GUID
)) < 0; }
255 size_t hash() const { //@@@ revisit this hash
256 return Data1
+ Data2
<< 3 + Data3
<< 11 + Data4
[3] + Data4
[6] << 22;
259 static const unsigned stringRepLength
= 38; // "{x8-x4-x4-x4-x12}"
260 char *toString(char buffer
[stringRepLength
+1]) const; // will append \0
261 Guid(const char *string
);
266 // User-friendly CSSM_SUBSERVICE_UIDs
268 class CssmSubserviceUid
: public PodWrapper
<CssmSubserviceUid
, CSSM_SUBSERVICE_UID
> {
270 CssmSubserviceUid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
271 CssmSubserviceUid(const CSSM_SUBSERVICE_UID
&rSSuid
) { memcpy(this, &rSSuid
, sizeof(*this)); }
273 CssmSubserviceUid
&operator = (const CSSM_SUBSERVICE_UID
&rSSuid
)
274 { memcpy(this, &rSSuid
, sizeof(CSSM_SUBSERVICE_UID
)); return *this; }
276 bool operator == (const CSSM_SUBSERVICE_UID
&other
) const
277 { return (this == &other
) || !memcmp(this, &other
, sizeof(CSSM_SUBSERVICE_UID
)); }
278 bool operator != (const CSSM_SUBSERVICE_UID
&other
) const
279 { return (this != &other
) && memcmp(this, &other
, sizeof(CSSM_SUBSERVICE_UID
)); }
280 bool operator < (const CSSM_SUBSERVICE_UID
&other
) const
281 { return memcmp(this, &other
, sizeof(CSSM_SUBSERVICE_UID
)) < 0; }
283 CssmSubserviceUid(const CSSM_GUID
&guid
, const CSSM_VERSION
*version
= NULL
,
284 uint32 subserviceId
= 0,
285 CSSM_SERVICE_TYPE subserviceType
= CSSM_SERVICE_DL
)
287 Guid
=guid
;SubserviceId
=subserviceId
;SubserviceType
=subserviceType
;
291 { Version
.Major
=0; Version
.Minor
=0; }
294 const ::Guid
&guid() const { return ::Guid::overlay(Guid
); }
295 uint32
subserviceId() const { return SubserviceId
; }
296 CSSM_SERVICE_TYPE
subserviceType() const { return SubserviceType
; }
297 CSSM_VERSION
version() const { return Version
; }
302 // User-friendlier CSSM_DATA thingies.
303 // CssmData is a PODWrapper and has no memory allocation features.
305 class CssmData
: public PodWrapper
<CssmData
, CSSM_DATA
> {
307 CssmData() { Data
= 0; Length
= 0; }
309 size_t length() const { return Length
; }
310 void *data() const { return Data
; }
311 void *end() const { return Data
+ Length
; }
314 // Create a CssmData from any pointer-to-byte-sized-object and length.
316 CssmData(void *data
, size_t length
)
317 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
318 CssmData(char *data
, size_t length
)
319 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
320 CssmData(unsigned char *data
, size_t length
)
321 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
322 CssmData(signed char *data
, size_t length
)
323 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
325 // the void * form accepts too much; explicitly deny all other types
326 private: template <class T
> CssmData(T
*, size_t); public:
329 // Do allow generic "wrapping" of any data structure, but make it conspicuous
330 // since it's not necessarily the Right Thing (alignment and byte order wise).
331 // Also note that the T & form removes const-ness, since there is no ConstCssmData.
334 static CssmData
wrap(const T
&it
)
335 { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it
)), sizeof(it
)); }
338 static CssmData
wrap(T
*data
, size_t length
)
339 { return CssmData(static_cast<void *>(data
), length
); }
342 // Automatically convert a CssmData to any pointer-to-byte-sized-type.
344 operator signed char * () const { return reinterpret_cast<signed char *>(Data
); }
345 operator unsigned char * () const { return reinterpret_cast<unsigned char *>(Data
); }
346 operator char * () const { return reinterpret_cast<char *>(Data
); }
347 operator void * () const { return reinterpret_cast<void *>(Data
); }
350 // If you want to interprete the contents of a CssmData blob as a particular
351 // type, you have to be more explicit to show that you know what you're doing.
355 T
*interpretedAs() const { return reinterpret_cast<T
*>(Data
); }
358 T
*interpretedAs(size_t len
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
) const
360 if (length() != len
) CssmError::throwMe(error
);
361 return interpretedAs
<T
>();
365 void length(size_t newLength
) // shorten only
366 { assert(newLength
<= Length
); Length
= newLength
; }
368 void *at(off_t offset
) const
369 { assert(offset
>= 0 && offset
<= Length
); return Data
+ offset
; }
370 void *at(off_t offset
, size_t size
) const // length-checking version
371 { assert(offset
>= 0 && offset
+ size
<= Length
); return Data
+ offset
; }
373 unsigned char operator [] (size_t pos
) const
374 { assert(pos
< Length
); return Data
[pos
]; }
375 void *use(size_t taken
) // logically remove some bytes
376 { assert(taken
<= Length
); void *r
= Data
; Length
-= taken
; Data
+= taken
; return r
; }
379 { Data
= NULL
; Length
= 0; }
381 string
toString () const; // convert to string type (no trailing null)
383 operator bool () const { return Data
!= NULL
; }
384 bool operator ! () const { return Data
== NULL
; }
385 bool operator < (const CssmData
&other
) const;
386 bool operator == (const CssmData
&other
) const
387 { return length() == other
.length() && !memcmp(data(), other
.data(), length()); }
388 bool operator != (const CssmData
&other
) const
389 { return !(*this == other
); }
391 // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you.
393 void extract(T
&destination
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
) const
395 if (length() != sizeof(destination
) || data() == NULL
)
396 CssmError::throwMe(error
);
397 memcpy(&destination
, data(), sizeof(destination
));
402 inline bool CssmData::operator < (const CssmData
&other
) const
404 if (Length
!= other
.Length
) // If lengths are not equal the shorter data is smaller.
405 return Length
< other
.Length
;
406 if (Length
== 0) // If lengths are both zero ignore the Data.
408 if (Data
== NULL
|| other
.Data
== NULL
) // arbitrary (but consistent) ordering
409 return Data
< other
.Data
;
410 return memcmp(Data
, other
.Data
, Length
) < 0; // Do a lexicographic compare on equal sized Data.
415 // User-friendler CSSM_CRYPTO_DATA objects
417 class CryptoCallback
{
419 CryptoCallback(CSSM_CALLBACK func
, void *ctx
= NULL
) : mFunction(func
), mCtx(ctx
) { }
420 CSSM_CALLBACK
function() const { return mFunction
; }
421 void *context() const { return mCtx
; }
423 CssmData
operator () () const
426 if (CSSM_RETURN err
= mFunction(&output
, mCtx
))
427 CssmError::throwMe(err
);
432 CSSM_CALLBACK mFunction
;
436 class CssmCryptoData
: public PodWrapper
<CssmCryptoData
, CSSM_CRYPTO_DATA
> {
440 CssmCryptoData(const CssmData
¶m
, CSSM_CALLBACK callback
= NULL
, void *ctx
= NULL
)
441 { Param
= const_cast<CssmData
&>(param
); Callback
= callback
; CallerCtx
= ctx
; }
443 CssmCryptoData(const CssmData
¶m
, CryptoCallback
&cb
)
444 { Param
= const_cast<CssmData
&>(param
); Callback
= cb
.function(); CallerCtx
= cb
.context(); }
446 CssmCryptoData(CSSM_CALLBACK callback
, void *ctx
= NULL
)
447 { /* ignore Param */ Callback
= callback
; CallerCtx
= ctx
; }
449 explicit CssmCryptoData(CryptoCallback
&cb
)
450 { /* ignore Param */ Callback
= cb
.function(); CallerCtx
= cb
.context(); }
453 CssmData
¶m() { return CssmData::overlay(Param
); }
454 const CssmData
¶m() const { return CssmData::overlay(Param
); }
455 bool hasCallback() const { return Callback
!= NULL
; }
456 CryptoCallback
callback() const { return CryptoCallback(Callback
, CallerCtx
); }
458 // get the value, whichever way is appropriate
459 CssmData
operator () () const
460 { return hasCallback() ? callback() () : param(); }
463 // a CssmCryptoContext whose callback is a virtual class member
464 class CryptoDataClass
: public CssmCryptoData
{
466 CryptoDataClass() : CssmCryptoData(callbackShim
, this) { }
467 virtual ~CryptoDataClass();
470 virtual CssmData
yield() = 0; // must subclass and implement this
473 static CSSM_RETURN
callbackShim(CSSM_DATA
*output
, void *ctx
)
476 *output
= reinterpret_cast<CryptoDataClass
*>(ctx
)->yield();
483 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
485 typedef CssmData CssmOid
;
489 // User-friendlier CSSM_KEY objects
491 class CssmKey
: public PodWrapper
<CssmKey
, CSSM_KEY
> {
493 CssmKey() { KeyHeader
.HeaderVersion
= CSSM_KEYHEADER_VERSION
; }
494 CssmKey(CSSM_KEY
&key
);
495 CssmKey(CSSM_DATA
&keyData
);
496 CssmKey(uint32 length
, uint8
*data
);
499 class Header
: public PodWrapper
<Header
, CSSM_KEYHEADER
> {
501 // access to components of the key header
502 CSSM_KEYBLOB_TYPE
blobType() const { return BlobType
; }
503 void blobType(CSSM_KEYBLOB_TYPE blobType
) { BlobType
= blobType
; }
505 CSSM_KEYBLOB_FORMAT
blobFormat() const { return Format
; }
506 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { Format
= blobFormat
; }
508 CSSM_KEYCLASS
keyClass() const { return KeyClass
; }
509 void keyClass(CSSM_KEYCLASS keyClass
) { KeyClass
= keyClass
; }
511 CSSM_KEY_TYPE
algorithm() const { return AlgorithmId
; }
512 void algorithm(CSSM_KEY_TYPE algorithm
) { AlgorithmId
= algorithm
; }
514 CSSM_KEY_TYPE
wrapAlgorithm() const { return WrapAlgorithmId
; }
515 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { WrapAlgorithmId
= wrapAlgorithm
; }
517 CSSM_ENCRYPT_MODE
wrapMode() const { return WrapMode
; }
518 void wrapMode(CSSM_ENCRYPT_MODE mode
) { WrapMode
= mode
; }
520 bool isWrapped() const { return WrapAlgorithmId
!= CSSM_ALGID_NONE
; }
522 const Guid
&cspGuid() const { return Guid::overlay(CspId
); }
523 void cspGuid(const Guid
&guid
) { Guid::overlay(CspId
) = guid
; }
525 uint32
attributes() const { return KeyAttr
; }
526 bool attribute(uint32 attr
) const { return KeyAttr
& attr
; }
527 void setAttribute(uint32 attr
) { KeyAttr
|= attr
; }
528 void clearAttribute(uint32 attr
) { KeyAttr
&= ~attr
; }
530 uint32
usage() const { return KeyUsage
; }
531 bool useFor(uint32 u
) const { return KeyUsage
& u
; }
533 void usage(uint32 u
) { KeyUsage
|= u
; }
534 void clearUsage(uint32 u
) { u
&= ~u
; }
538 // access to the key header
539 Header
&header() { return Header::overlay(KeyHeader
); }
540 const Header
&header() const { return Header::overlay(KeyHeader
); }
542 CSSM_KEYBLOB_TYPE
blobType() const { return header().blobType(); }
543 void blobType(CSSM_KEYBLOB_TYPE blobType
) { header().blobType(blobType
); }
545 CSSM_KEYBLOB_FORMAT
blobFormat() const { return header().blobFormat(); }
546 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { header().blobFormat(blobFormat
); }
548 CSSM_KEYCLASS
keyClass() const { return header().keyClass(); }
549 void keyClass(CSSM_KEYCLASS keyClass
) { header().keyClass(keyClass
); }
551 CSSM_KEY_TYPE
algorithm() const { return header().algorithm(); }
552 void algorithm(CSSM_KEY_TYPE algorithm
) { header().algorithm(algorithm
); }
554 CSSM_KEY_TYPE
wrapAlgorithm() const { return header().wrapAlgorithm(); }
555 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { header().wrapAlgorithm(wrapAlgorithm
); }
557 CSSM_ENCRYPT_MODE
wrapMode() const { return header().wrapMode(); }
558 void wrapMode(CSSM_ENCRYPT_MODE mode
) { header().wrapMode(mode
); }
560 bool isWrapped() const { return header().isWrapped(); }
561 const Guid
&cspGuid() const { return header().cspGuid(); }
563 uint32
attributes() const { return header().attributes(); }
564 bool attribute(uint32 a
) const { return header().attribute(a
); }
565 void setAttribute(uint32 attr
) { header().setAttribute(attr
); }
566 void clearAttribute(uint32 attr
) { header().clearAttribute(attr
); }
568 uint32
usage() const { return header().usage(); }
569 bool useFor(uint32 u
) const { return header().useFor(u
); }
571 void usage(uint32 u
) { header().usage(u
); }
572 void clearUsage(uint32 u
) { header().clearUsage(u
); }
575 // access to the key data
576 size_t length() const { return KeyData
.Length
; }
577 void *data() const { return KeyData
.Data
; }
578 operator void * () const { return data(); }
579 operator CssmData
& () { return CssmData::overlay(KeyData
); }
580 operator const CssmData
& () const { return static_cast<const CssmData
&>(KeyData
); }
581 operator bool () const { return KeyData
.Data
!= NULL
; }
582 void operator = (const CssmData
&data
) { KeyData
= data
; }
587 // Wrapped keys are currently identically structured to normal keys.
588 // But perhaps in the future...
590 typedef CssmKey CssmWrappedKey
;
594 // Other PodWrappers for stuff that is barely useful...
596 class CssmKeySize
: public PodWrapper
<CssmKeySize
, CSSM_KEY_SIZE
> {
599 CssmKeySize(uint32 nom
, uint32 eff
) { LogicalKeySizeInBits
= nom
; EffectiveKeySizeInBits
= eff
; }
600 CssmKeySize(uint32 size
) { LogicalKeySizeInBits
= EffectiveKeySizeInBits
= size
; }
602 uint32
logical() const { return LogicalKeySizeInBits
; }
603 uint32
effective() const { return EffectiveKeySizeInBits
; }
604 operator uint32 () const { return effective(); }
607 inline bool operator == (const CSSM_KEY_SIZE
&s1
, const CSSM_KEY_SIZE
&s2
)
609 return s1
.LogicalKeySizeInBits
== s2
.LogicalKeySizeInBits
610 && s1
.EffectiveKeySizeInBits
== s2
.EffectiveKeySizeInBits
;
613 inline bool operator != (const CSSM_KEY_SIZE
&s1
, const CSSM_KEY_SIZE
&s2
)
614 { return !(s1
== s2
); }
617 class QuerySizeData
: public PodWrapper
<QuerySizeData
, CSSM_QUERY_SIZE_DATA
> {
620 QuerySizeData(uint32 in
) { SizeInputBlock
= in
; SizeOutputBlock
= 0; }
622 uint32
inputSize() const { return SizeInputBlock
; }
623 uint32
inputSize(uint32 size
) { return SizeInputBlock
= size
; }
624 uint32
outputSize() const { return SizeOutputBlock
; }
627 inline bool operator == (const CSSM_QUERY_SIZE_DATA
&s1
, const CSSM_QUERY_SIZE_DATA
&s2
)
629 return s1
.SizeInputBlock
== s2
.SizeInputBlock
630 && s1
.SizeOutputBlock
== s2
.SizeOutputBlock
;
633 inline bool operator != (const CSSM_QUERY_SIZE_DATA
&s1
, const CSSM_QUERY_SIZE_DATA
&s2
)
634 { return !(s1
== s2
); }
637 class CSPOperationalStatistics
:
638 public PodWrapper
<CSPOperationalStatistics
, CSSM_CSP_OPERATIONAL_STATISTICS
> {
644 // User-friendli(er) DL queries.
645 // @@@ Preliminary (flesh out as needed)
647 class DLQuery
: public PodWrapper
<DLQuery
, CSSM_QUERY
> {
649 DLQuery() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
650 DLQuery(const CSSM_QUERY
&q
) { memcpy(this, &q
, sizeof(*this)); }
652 DLQuery
&operator = (const CSSM_QUERY
&q
)
653 { memcpy(this, &q
, sizeof(*this)); return *this; }
657 // Help with container of something->pointer cleanup
659 static inline void for_each_delete(In first
, In last
)
661 while (first
!= last
)
665 // Help with map of something->pointer cleanup
667 static inline void for_each_map_delete(In first
, In last
)
669 while (first
!= last
)
670 delete (first
++)->second
;
673 // Quick and dirty template for a (temporary) array of something
674 // Usage example auto_array<uint32> anArray(20);
679 auto_array() : mArray(NULL
) {}
680 auto_array(size_t inSize
) : mArray(new T
[inSize
]) {}
681 ~auto_array() { if (mArray
) delete[] mArray
; }
682 T
&operator[](size_t inIndex
) { return mArray
[inIndex
]; }
683 void allocate(size_t inSize
) { if (mArray
) delete[] mArray
; mArray
= new T
[inSize
]; }
684 T
*get() { return mArray
; }
685 T
*release() { T
*anArray
= mArray
; mArray
= NULL
; return anArray
; }
690 // Template for a vector-like class that takes a c-array as it's
691 // underlying storage without making a copy.
695 NOCOPY(constVector
<_Tp
>)
697 typedef _Tp value_type
;
698 typedef const value_type
* const_pointer
;
699 typedef const value_type
* const_iterator
;
700 typedef const value_type
& const_reference
;
701 typedef size_t size_type
;
702 typedef ptrdiff_t difference_type
;
704 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
706 const_iterator
begin() const { return _M_start
; }
707 const_iterator
end() const { return _M_finish
; }
709 const_reverse_iterator
rbegin() const
710 { return const_reverse_iterator(end()); }
711 const_reverse_iterator
rend() const
712 { return const_reverse_iterator(begin()); }
714 size_type
size() const
715 { return size_type(end() - begin()); }
717 { return begin() == end(); }
719 const_reference
operator[](size_type __n
) const { return *(begin() + __n
); }
721 // "at" will eventually have range checking, once we have the
722 // infrastructure to be able to throw stl range errors.
723 const_reference
at(size_type n
) const { return (*this)[n
]; }
725 constVector(size_type __n
, const _Tp
* __value
)
726 : _M_start(__value
), _M_finish(__value
+ __n
)
729 constVector() : _M_start(NULL
), _M_finish(NULL
) {}
731 void overlay(size_type __n
, const _Tp
* __value
) {
733 _M_finish
= __value
+ __n
;
736 const_reference
front() const { return *begin(); }
737 const_reference
back() const { return *(end() - 1); }
740 const _Tp
*_M_finish
;
744 } // end namespace Security
748 // Strictly as a transition measure, include cfutilities.h here
750 #include "cfutilities.h"
753 #endif //_H_UTILITIES