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;
98 virtual int unixError() const;
101 virtual void debugDiagnose(const void *id
) const; // used internally for debug logging
104 IFDEBUG(mutable bool mCarrier
); // primary carrier of exception flow
107 class CssmError
: public CssmCommonError
{
109 CssmError(CSSM_RETURN err
);
111 const CSSM_RETURN error
;
112 virtual CSSM_RETURN
cssmError() const;
113 virtual OSStatus
osStatus() const;
114 virtual const char *what () const throw ();
116 static CSSM_RETURN
merge(CSSM_RETURN error
, CSSM_RETURN base
);
118 static void check(CSSM_RETURN error
) { if (error
!= CSSM_OK
) throwMe(error
); }
119 static void throwMe(CSSM_RETURN error
) __attribute__((noreturn
));
122 class UnixError
: public CssmCommonError
{
128 virtual CSSM_RETURN
cssmError() const;
129 virtual OSStatus
osStatus() const;
130 virtual int unixError() const;
131 virtual const char *what () const throw ();
133 static void check(int result
) { if (result
== -1) throwMe(); }
134 static void throwMe(int err
= errno
) __attribute__((noreturn
));
136 // @@@ This is a hack for the Network protocol state machine
137 static UnixError
make(int err
= errno
);
140 IFDEBUG(void debugDiagnose(const void *id
) const);
143 class MacOSError
: public CssmCommonError
{
148 virtual CSSM_RETURN
cssmError() const;
149 virtual OSStatus
osStatus() const;
150 virtual const char *what () const throw ();
152 static void check(OSStatus status
) { if (status
!= noErr
) throwMe(status
); }
153 static void throwMe(int err
) __attribute__((noreturn
));
158 // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions.
161 // ... your C++ code here ...
162 // END_API(base) // returns CSSM_RETURN on exception; complete it to 'base' (DL, etc.) class;
163 // // returns CSSM_OK on fall-through
164 // END_API0 // completely ignores exceptions; falls through in all cases
165 // END_API1(bad) // return (bad) on exception; fall through on success
167 #define BEGIN_API try {
168 #define END_API(base) } \
169 catch (const CssmCommonError &err) { return err.cssmError(CSSM_ ## base ## _BASE_ERROR); } \
170 catch (const std::bad_alloc &) { return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
171 catch (...) { return CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
173 #define END_API0 } catch (...) { return; }
174 #define END_API1(bad) } catch (...) { return bad; }
178 // Helpers for memory pointer validation
181 inline T
&Required(T
*ptr
, CSSM_RETURN err
= CSSM_ERRCODE_INVALID_POINTER
)
184 CssmError::throwMe(err
);
188 // specialization for void * (just check for non-null; don't return a void & :-)
189 inline void Required(void *ptr
, CSSM_RETURN err
= CSSM_ERRCODE_INVALID_POINTER
)
192 CssmError::throwMe(err
);
197 // Tools to build POD wrapper classes
199 template <class Wrapper
, class POD
>
200 class PodWrapper
: public POD
{
203 static Wrapper
* &overlayVar(POD
* &data
)
204 { return reinterpret_cast<Wrapper
* &>(data
); }
205 static const Wrapper
* &overlayVar(const POD
* &data
)
206 { return reinterpret_cast<const Wrapper
* &>(data
); }
208 static Wrapper
*overlay(POD
*data
)
209 { return static_cast<Wrapper
*>(data
); }
210 static const Wrapper
*overlay(const POD
*data
)
211 { return static_cast<const Wrapper
*>(data
); }
212 static Wrapper
&overlay(POD
&data
)
213 { return static_cast<Wrapper
&>(data
); }
214 static const Wrapper
&overlay(const POD
&data
)
215 { return static_cast<const Wrapper
&>(data
); }
217 // optional/required forms
218 static Wrapper
&required(POD
*data
)
219 { return overlay(Required(data
)); }
220 static const Wrapper
&required(const POD
*data
)
221 { return overlay(Required(data
)); }
222 static Wrapper
*optional(POD
*data
)
223 { return overlay(data
); }
224 static const Wrapper
*optional(const POD
*data
)
225 { return overlay(data
); }
227 // general helpers for all PodWrappers
229 { memset(static_cast<POD
*>(this), 0, sizeof(POD
)); }
234 // Template builder support
242 struct Nonconst
<const U
> {
248 // User-friendly GUIDs
250 class Guid
: public PodWrapper
<Guid
, CSSM_GUID
> {
252 Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
253 Guid(const CSSM_GUID
&rGuid
) { memcpy(this, &rGuid
, sizeof(*this)); }
255 Guid
&operator = (const CSSM_GUID
&rGuid
)
256 { memcpy(this, &rGuid
, sizeof(CSSM_GUID
)); return *this; }
258 bool operator == (const CSSM_GUID
&other
) const
259 { return (this == &other
) || !memcmp(this, &other
, sizeof(CSSM_GUID
)); }
260 bool operator != (const CSSM_GUID
&other
) const
261 { return (this != &other
) && memcmp(this, &other
, sizeof(CSSM_GUID
)); }
262 bool operator < (const CSSM_GUID
&other
) const
263 { return memcmp(this, &other
, sizeof(CSSM_GUID
)) < 0; }
264 size_t hash() const { //@@@ revisit this hash
265 return Data1
+ Data2
<< 3 + Data3
<< 11 + Data4
[3] + Data4
[6] << 22;
268 static const unsigned stringRepLength
= 38; // "{x8-x4-x4-x4-x12}"
269 char *toString(char buffer
[stringRepLength
+1]) const; // will append \0
270 Guid(const char *string
);
275 // User-friendly CSSM_SUBSERVICE_UIDs
277 class CssmSubserviceUid
: public PodWrapper
<CssmSubserviceUid
, CSSM_SUBSERVICE_UID
> {
279 CssmSubserviceUid() { clearPod(); }
280 CssmSubserviceUid(const CSSM_SUBSERVICE_UID
&rSSuid
) { memcpy(this, &rSSuid
, sizeof(*this)); }
282 CssmSubserviceUid
&operator = (const CSSM_SUBSERVICE_UID
&rSSuid
)
283 { memcpy(this, &rSSuid
, sizeof(CSSM_SUBSERVICE_UID
)); return *this; }
285 bool operator == (const CSSM_SUBSERVICE_UID
&other
) const;
286 bool operator != (const CSSM_SUBSERVICE_UID
&other
) const { return !(*this == other
); }
287 bool operator < (const CSSM_SUBSERVICE_UID
&other
) const;
289 CssmSubserviceUid(const CSSM_GUID
&guid
, const CSSM_VERSION
*version
= NULL
,
290 uint32 subserviceId
= 0,
291 CSSM_SERVICE_TYPE subserviceType
= CSSM_SERVICE_DL
);
293 const ::Guid
&guid() const { return ::Guid::overlay(Guid
); }
294 uint32
subserviceId() const { return SubserviceId
; }
295 CSSM_SERVICE_TYPE
subserviceType() const { return SubserviceType
; }
296 CSSM_VERSION
version() const { return Version
; }
301 // User-friendlier CSSM_DATA thingies.
302 // CssmData is a PODWrapper and has no memory allocation features.
304 class CssmData
: public PodWrapper
<CssmData
, CSSM_DATA
> {
306 CssmData() { Data
= 0; Length
= 0; }
308 size_t length() const { return Length
; }
309 void *data() const { return Data
; }
310 void *end() const { return Data
+ Length
; }
313 // Create a CssmData from any pointer-to-byte-sized-object and length.
315 CssmData(void *data
, size_t length
)
316 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
317 CssmData(char *data
, size_t length
)
318 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
319 CssmData(unsigned char *data
, size_t length
)
320 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
321 CssmData(signed char *data
, size_t length
)
322 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
324 // the void * form accepts too much; explicitly deny all other types
325 private: template <class T
> CssmData(T
*, size_t); public:
327 // explicitly construct from a data-oid source
329 explicit CssmData(const T
&obj
)
330 { Data
= (UInt8
*)obj
.data(); Length
= obj
.length(); }
333 // Do allow generic "wrapping" of any data structure, but make it conspicuous
334 // since it's not necessarily the Right Thing (alignment and byte order wise).
335 // Also note that the T & form removes const-ness, since there is no ConstCssmData.
338 static CssmData
wrap(const T
&it
)
339 { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it
)), sizeof(it
)); }
342 static CssmData
wrap(T
*data
, size_t length
)
343 { return CssmData(static_cast<void *>(data
), length
); }
346 // Automatically convert a CssmData to any pointer-to-byte-sized-type.
348 operator signed char * () const { return reinterpret_cast<signed char *>(Data
); }
349 operator unsigned char * () const { return reinterpret_cast<unsigned char *>(Data
); }
350 operator char * () const { return reinterpret_cast<char *>(Data
); }
351 operator void * () const { return reinterpret_cast<void *>(Data
); }
354 // If you want to interpret the contents of a CssmData blob as a particular
355 // type, you have to be more explicit to show that you know what you're doing.
359 T
*interpretedAs() const { return reinterpret_cast<T
*>(Data
); }
362 T
*interpretedAs(CSSM_RETURN error
) const
363 { return interpretedAs
<T
>(sizeof(T
), error
); }
366 T
*interpretedAs(size_t len
, CSSM_RETURN error
) const
368 if (data() == NULL
|| length() != len
) CssmError::throwMe(error
);
369 return interpretedAs
<T
>();
373 void length(size_t newLength
) // shorten only
374 { assert(newLength
<= Length
); Length
= newLength
; }
376 void *at(off_t offset
) const
377 { assert(offset
>= 0 && offset
<= Length
); return Data
+ offset
; }
378 void *at(off_t offset
, size_t size
) const // length-checking version
379 { assert(offset
>= 0 && offset
+ size
<= Length
); return Data
+ offset
; }
381 unsigned char operator [] (size_t pos
) const
382 { assert(pos
< Length
); return Data
[pos
]; }
383 void *use(size_t taken
) // logically remove some bytes
384 { assert(taken
<= Length
); void *r
= Data
; Length
-= taken
; Data
+= taken
; return r
; }
387 { Data
= NULL
; Length
= 0; }
389 string
toString () const; // convert to string type (no trailing null)
391 operator bool () const { return Data
!= NULL
; }
392 bool operator ! () const { return Data
== NULL
; }
393 bool operator < (const CssmData
&other
) const;
394 bool operator == (const CssmData
&other
) const
395 { return length() == other
.length() && !memcmp(data(), other
.data(), length()); }
396 bool operator != (const CssmData
&other
) const
397 { return !(*this == other
); }
399 // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you.
401 void extract(T
&destination
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
) const
403 if (length() != sizeof(destination
) || data() == NULL
)
404 CssmError::throwMe(error
);
405 memcpy(&destination
, data(), sizeof(destination
));
410 inline bool CssmData::operator < (const CssmData
&other
) const
412 if (Length
!= other
.Length
) // If lengths are not equal the shorter data is smaller.
413 return Length
< other
.Length
;
414 if (Length
== 0) // If lengths are both zero ignore the Data.
416 if (Data
== NULL
|| other
.Data
== NULL
) // arbitrary (but consistent) ordering
417 return Data
< other
.Data
;
418 return memcmp(Data
, other
.Data
, Length
) < 0; // Do a lexicographic compare on equal sized Data.
423 // User-friendler CSSM_CRYPTO_DATA objects
425 class CryptoCallback
{
427 CryptoCallback(CSSM_CALLBACK func
, void *ctx
= NULL
) : mFunction(func
), mCtx(ctx
) { }
428 CSSM_CALLBACK
function() const { return mFunction
; }
429 void *context() const { return mCtx
; }
431 CssmData
operator () () const
434 if (CSSM_RETURN err
= mFunction(&output
, mCtx
))
435 CssmError::throwMe(err
);
440 CSSM_CALLBACK mFunction
;
444 class CssmCryptoData
: public PodWrapper
<CssmCryptoData
, CSSM_CRYPTO_DATA
> {
448 CssmCryptoData(const CssmData
¶m
, CSSM_CALLBACK callback
= NULL
, void *ctx
= NULL
)
449 { Param
= const_cast<CssmData
&>(param
); Callback
= callback
; CallerCtx
= ctx
; }
451 CssmCryptoData(const CssmData
¶m
, CryptoCallback
&cb
)
452 { Param
= const_cast<CssmData
&>(param
); Callback
= cb
.function(); CallerCtx
= cb
.context(); }
454 CssmCryptoData(CSSM_CALLBACK callback
, void *ctx
= NULL
)
455 { /* ignore Param */ Callback
= callback
; CallerCtx
= ctx
; }
457 explicit CssmCryptoData(CryptoCallback
&cb
)
458 { /* ignore Param */ Callback
= cb
.function(); CallerCtx
= cb
.context(); }
461 CssmData
¶m() { return CssmData::overlay(Param
); }
462 const CssmData
¶m() const { return CssmData::overlay(Param
); }
463 bool hasCallback() const { return Callback
!= NULL
; }
464 CryptoCallback
callback() const { return CryptoCallback(Callback
, CallerCtx
); }
466 // get the value, whichever way is appropriate
467 CssmData
operator () () const
468 { return hasCallback() ? callback() () : param(); }
471 // a CssmCryptoContext whose callback is a virtual class member
472 class CryptoDataClass
: public CssmCryptoData
{
474 CryptoDataClass() : CssmCryptoData(callbackShim
, this) { }
475 virtual ~CryptoDataClass();
478 virtual CssmData
yield() = 0; // must subclass and implement this
481 static CSSM_RETURN
callbackShim(CSSM_DATA
*output
, void *ctx
)
484 *output
= reinterpret_cast<CryptoDataClass
*>(ctx
)->yield();
491 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
493 typedef CssmData CssmOid
;
497 // User-friendlier CSSM_KEY objects
499 class CssmKey
: public PodWrapper
<CssmKey
, CSSM_KEY
> {
501 CssmKey() { clearPod(); KeyHeader
.HeaderVersion
= CSSM_KEYHEADER_VERSION
; }
502 // all of the following constructors take over ownership of the key data
503 CssmKey(const CSSM_KEY
&key
);
504 CssmKey(const CSSM_DATA
&keyData
);
505 CssmKey(uint32 length
, void *data
);
508 class Header
: public PodWrapper
<Header
, CSSM_KEYHEADER
> {
510 // access to components of the key header
511 CSSM_KEYBLOB_TYPE
blobType() const { return BlobType
; }
512 void blobType(CSSM_KEYBLOB_TYPE blobType
) { BlobType
= blobType
; }
514 CSSM_KEYBLOB_FORMAT
blobFormat() const { return Format
; }
515 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { Format
= blobFormat
; }
517 CSSM_KEYCLASS
keyClass() const { return KeyClass
; }
518 void keyClass(CSSM_KEYCLASS keyClass
) { KeyClass
= keyClass
; }
520 CSSM_KEY_TYPE
algorithm() const { return AlgorithmId
; }
521 void algorithm(CSSM_KEY_TYPE algorithm
) { AlgorithmId
= algorithm
; }
523 CSSM_KEY_TYPE
wrapAlgorithm() const { return WrapAlgorithmId
; }
524 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { WrapAlgorithmId
= wrapAlgorithm
; }
526 CSSM_ENCRYPT_MODE
wrapMode() const { return WrapMode
; }
527 void wrapMode(CSSM_ENCRYPT_MODE mode
) { WrapMode
= mode
; }
529 bool isWrapped() const { return WrapAlgorithmId
!= CSSM_ALGID_NONE
; }
531 const Guid
&cspGuid() const { return Guid::overlay(CspId
); }
532 void cspGuid(const Guid
&guid
) { Guid::overlay(CspId
) = guid
; }
534 uint32
attributes() const { return KeyAttr
; }
535 bool attribute(uint32 attr
) const { return KeyAttr
& attr
; }
536 void setAttribute(uint32 attr
) { KeyAttr
|= attr
; }
537 void clearAttribute(uint32 attr
) { KeyAttr
&= ~attr
; }
539 uint32
usage() const { return KeyUsage
; }
540 bool useFor(uint32 u
) const { return KeyUsage
& u
; }
542 void usage(uint32 u
) { KeyUsage
|= u
; }
543 void clearUsage(uint32 u
) { u
&= ~u
; }
547 // access to the key header
548 Header
&header() { return Header::overlay(KeyHeader
); }
549 const Header
&header() const { return Header::overlay(KeyHeader
); }
551 CSSM_KEYBLOB_TYPE
blobType() const { return header().blobType(); }
552 void blobType(CSSM_KEYBLOB_TYPE blobType
) { header().blobType(blobType
); }
554 CSSM_KEYBLOB_FORMAT
blobFormat() const { return header().blobFormat(); }
555 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { header().blobFormat(blobFormat
); }
557 CSSM_KEYCLASS
keyClass() const { return header().keyClass(); }
558 void keyClass(CSSM_KEYCLASS keyClass
) { header().keyClass(keyClass
); }
560 CSSM_KEY_TYPE
algorithm() const { return header().algorithm(); }
561 void algorithm(CSSM_KEY_TYPE algorithm
) { header().algorithm(algorithm
); }
563 CSSM_KEY_TYPE
wrapAlgorithm() const { return header().wrapAlgorithm(); }
564 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { header().wrapAlgorithm(wrapAlgorithm
); }
566 CSSM_ENCRYPT_MODE
wrapMode() const { return header().wrapMode(); }
567 void wrapMode(CSSM_ENCRYPT_MODE mode
) { header().wrapMode(mode
); }
569 bool isWrapped() const { return header().isWrapped(); }
570 const Guid
&cspGuid() const { return header().cspGuid(); }
572 uint32
attributes() const { return header().attributes(); }
573 bool attribute(uint32 a
) const { return header().attribute(a
); }
574 void setAttribute(uint32 attr
) { header().setAttribute(attr
); }
575 void clearAttribute(uint32 attr
) { header().clearAttribute(attr
); }
577 uint32
usage() const { return header().usage(); }
578 bool useFor(uint32 u
) const { return header().useFor(u
); }
580 void usage(uint32 u
) { header().usage(u
); }
581 void clearUsage(uint32 u
) { header().clearUsage(u
); }
584 // access to the key data
585 size_t length() const { return KeyData
.Length
; }
586 void *data() const { return KeyData
.Data
; }
587 operator void * () const { return data(); }
588 CssmData
&keyData() { return CssmData::overlay(KeyData
); }
589 const CssmData
&keyData() const { return CssmData::overlay(KeyData
); }
590 operator CssmData
& () { return keyData(); }
591 operator const CssmData
& () const { return keyData(); }
592 operator bool () const { return KeyData
.Data
!= NULL
; }
593 void operator = (const CssmData
&data
) { KeyData
= data
; }
598 // Wrapped keys are currently identically structured to normal keys.
599 // But perhaps in the future...
601 typedef CssmKey CssmWrappedKey
;
605 // Other PodWrappers for stuff that is barely useful...
607 class CssmKeySize
: public PodWrapper
<CssmKeySize
, CSSM_KEY_SIZE
> {
610 CssmKeySize(uint32 nom
, uint32 eff
) { LogicalKeySizeInBits
= nom
; EffectiveKeySizeInBits
= eff
; }
611 CssmKeySize(uint32 size
) { LogicalKeySizeInBits
= EffectiveKeySizeInBits
= size
; }
613 uint32
logical() const { return LogicalKeySizeInBits
; }
614 uint32
effective() const { return EffectiveKeySizeInBits
; }
615 operator uint32 () const { return effective(); }
618 inline bool operator == (const CSSM_KEY_SIZE
&s1
, const CSSM_KEY_SIZE
&s2
)
620 return s1
.LogicalKeySizeInBits
== s2
.LogicalKeySizeInBits
621 && s1
.EffectiveKeySizeInBits
== s2
.EffectiveKeySizeInBits
;
624 inline bool operator != (const CSSM_KEY_SIZE
&s1
, const CSSM_KEY_SIZE
&s2
)
625 { return !(s1
== s2
); }
628 class QuerySizeData
: public PodWrapper
<QuerySizeData
, CSSM_QUERY_SIZE_DATA
> {
631 QuerySizeData(uint32 in
) { SizeInputBlock
= in
; SizeOutputBlock
= 0; }
633 uint32
inputSize() const { return SizeInputBlock
; }
634 uint32
inputSize(uint32 size
) { return SizeInputBlock
= size
; }
635 uint32
outputSize() const { return SizeOutputBlock
; }
638 inline bool operator == (const CSSM_QUERY_SIZE_DATA
&s1
, const CSSM_QUERY_SIZE_DATA
&s2
)
640 return s1
.SizeInputBlock
== s2
.SizeInputBlock
641 && s1
.SizeOutputBlock
== s2
.SizeOutputBlock
;
644 inline bool operator != (const CSSM_QUERY_SIZE_DATA
&s1
, const CSSM_QUERY_SIZE_DATA
&s2
)
645 { return !(s1
== s2
); }
648 class CSPOperationalStatistics
:
649 public PodWrapper
<CSPOperationalStatistics
, CSSM_CSP_OPERATIONAL_STATISTICS
> {
655 // User-friendli(er) DL queries.
656 // @@@ Preliminary (flesh out as needed)
658 class DLQuery
: public PodWrapper
<DLQuery
, CSSM_QUERY
> {
660 DLQuery() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
661 DLQuery(const CSSM_QUERY
&q
) { memcpy(this, &q
, sizeof(*this)); }
663 DLQuery
&operator = (const CSSM_QUERY
&q
)
664 { memcpy(this, &q
, sizeof(*this)); return *this; }
668 // Help with container of something->pointer cleanup
670 static inline void for_each_delete(In first
, In last
)
672 while (first
!= last
)
676 // Help with map of something->pointer cleanup
678 static inline void for_each_map_delete(In first
, In last
)
680 while (first
!= last
)
681 delete (first
++)->second
;
684 // Quick and dirty template for a (temporary) array of something
685 // Usage example auto_array<uint32> anArray(20);
690 auto_array() : mArray(NULL
) {}
691 auto_array(size_t inSize
) : mArray(new T
[inSize
]) {}
692 ~auto_array() { if (mArray
) delete[] mArray
; }
693 T
&operator[](size_t inIndex
) { return mArray
[inIndex
]; }
694 void allocate(size_t inSize
) { if (mArray
) delete[] mArray
; mArray
= new T
[inSize
]; }
695 T
*get() { return mArray
; }
696 T
*release() { T
*anArray
= mArray
; mArray
= NULL
; return anArray
; }
701 // Template for a vector-like class that takes a c-array as it's
702 // underlying storage without making a copy.
706 NOCOPY(constVector
<_Tp
>)
708 typedef _Tp value_type
;
709 typedef const value_type
* const_pointer
;
710 typedef const value_type
* const_iterator
;
711 typedef const value_type
& const_reference
;
712 typedef size_t size_type
;
713 typedef ptrdiff_t difference_type
;
715 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
717 const_iterator
begin() const { return _M_start
; }
718 const_iterator
end() const { return _M_finish
; }
720 const_reverse_iterator
rbegin() const
721 { return const_reverse_iterator(end()); }
722 const_reverse_iterator
rend() const
723 { return const_reverse_iterator(begin()); }
725 size_type
size() const
726 { return size_type(end() - begin()); }
728 { return begin() == end(); }
730 const_reference
operator[](size_type __n
) const { return *(begin() + __n
); }
732 // "at" will eventually have range checking, once we have the
733 // infrastructure to be able to throw stl range errors.
734 const_reference
at(size_type n
) const { return (*this)[n
]; }
736 constVector(size_type __n
, const _Tp
* __value
)
737 : _M_start(__value
), _M_finish(__value
+ __n
)
740 constVector() : _M_start(NULL
), _M_finish(NULL
) {}
742 void overlay(size_type __n
, const _Tp
* __value
) {
744 _M_finish
= __value
+ __n
;
747 const_reference
front() const { return *begin(); }
748 const_reference
back() const { return *(end() - 1); }
751 const _Tp
*_M_finish
;
755 } // end namespace Security
759 // Strictly as a transition measure, include cfutilities.h here
761 #include "cfutilities.h"
764 #endif //_H_UTILITIES