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 exception
{
91 CssmCommonError(const CssmCommonError
&source
);
93 virtual ~CssmCommonError();
95 virtual CSSM_RETURN
cssmError() const = 0;
96 virtual CSSM_RETURN
cssmError(CSSM_RETURN base
) const;
97 virtual OSStatus
osStatus() const;
100 class CssmError
: public CssmCommonError
{
102 CssmError(CSSM_RETURN err
);
104 const CSSM_RETURN error
;
105 virtual CSSM_RETURN
cssmError() const;
106 virtual OSStatus
osStatus() const;
107 virtual const char *what () const;
109 static CSSM_RETURN
merge(CSSM_RETURN error
, CSSM_RETURN base
);
111 static void throwMe(CSSM_RETURN error
) __attribute__((noreturn
));
114 class UnixError
: public CssmCommonError
{
120 virtual CSSM_RETURN
cssmError() const;
121 virtual OSStatus
osStatus() const;
122 virtual const char *what () const;
124 static void check(int result
) { if (result
== -1) throwMe(); }
125 static void throwMe(int err
= errno
) __attribute__((noreturn
));
127 // @@@ This is a hack for the Network protocol state machine
128 static UnixError
make(int err
= errno
);
131 class MacOSError
: public CssmCommonError
{
136 virtual CSSM_RETURN
cssmError() const;
137 virtual OSStatus
osStatus() const;
138 virtual const char *what () const;
140 static void check(OSStatus status
) { if (status
!= noErr
) throwMe(status
); }
141 static void throwMe(int err
) __attribute__((noreturn
));
146 // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions.
149 // ... your C++ code here ...
150 // END_API(base) // returns CSSM_RETURN on exception; complete it to 'base' (DL, etc.) class;
151 // // returns CSSM_OK on fall-through
152 // END_API0 // completely ignores exceptions; falls through in all cases
153 // END_API1(bad) // return (bad) on exception; fall through on success
155 #define BEGIN_API try {
156 #define END_API(base) } \
157 catch (const CssmCommonError &err) { return err.cssmError(CSSM_ ## base ## _BASE_ERROR); } \
158 catch (std::bad_alloc) { return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
159 catch (...) { return CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
161 #define END_API0 } catch (...) { return; }
162 #define END_API1(bad) } catch (...) { return bad; }
166 // Helpers for memory pointer validation
169 inline T
&Required(T
*ptr
, CSSM_RETURN err
= CSSM_ERRCODE_INVALID_POINTER
)
172 CssmError::throwMe(err
);
178 // Tools to build POD wrapper classes
180 template <class Wrapper
, class POD
>
181 class PodWrapper
: public POD
{
184 static Wrapper
* &overlayVar(POD
* &data
)
185 { return reinterpret_cast<Wrapper
* &>(data
); }
186 static const Wrapper
* &overlayVar(const POD
* &data
)
187 { return reinterpret_cast<const Wrapper
* &>(data
); }
189 static Wrapper
*overlay(POD
*data
)
190 { return static_cast<Wrapper
*>(data
); }
191 static const Wrapper
*overlay(const POD
*data
)
192 { return static_cast<const Wrapper
*>(data
); }
193 static Wrapper
&overlay(POD
&data
)
194 { return static_cast<Wrapper
&>(data
); }
195 static const Wrapper
&overlay(const POD
&data
)
196 { return static_cast<const Wrapper
&>(data
); }
198 // optional/required forms
199 static Wrapper
&required(POD
*data
)
200 { return overlay(Required(data
)); }
201 static const Wrapper
&required(const POD
*data
)
202 { return overlay(Required(data
)); }
203 static Wrapper
*optional(POD
*data
)
204 { return overlay(data
); }
205 static const Wrapper
*optional(const POD
*data
)
206 { return overlay(data
); }
211 // Template builder support
219 struct Nonconst
<const U
> {
225 // User-friendly GUIDs
227 class Guid
: public PodWrapper
<Guid
, CSSM_GUID
> {
229 Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
230 Guid(const CSSM_GUID
&rGuid
) { memcpy(this, &rGuid
, sizeof(*this)); }
232 Guid
&operator = (const CSSM_GUID
&rGuid
)
233 { memcpy(this, &rGuid
, sizeof(CSSM_GUID
)); return *this; }
235 bool operator == (const CSSM_GUID
&other
) const
236 { return (this == &other
) || !memcmp(this, &other
, sizeof(CSSM_GUID
)); }
237 bool operator != (const CSSM_GUID
&other
) const
238 { return (this != &other
) && memcmp(this, &other
, sizeof(CSSM_GUID
)); }
239 bool operator < (const CSSM_GUID
&other
) const
240 { return memcmp(this, &other
, sizeof(CSSM_GUID
)) < 0; }
241 size_t hash() const { //@@@ revisit this hash
242 return Data1
+ Data2
<< 3 + Data3
<< 11 + Data4
[3] + Data4
[6] << 22;
245 static const unsigned stringRepLength
= 38; // "{x8-x4-x4-x4-x12}"
246 char *toString(char buffer
[stringRepLength
+1]) const; // will append \0
247 Guid(const char *string
);
252 // User-friendly CSSM_SUBSERVICE_UIDs
254 class CssmSubserviceUid
: public PodWrapper
<CssmSubserviceUid
, CSSM_SUBSERVICE_UID
> {
256 CssmSubserviceUid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
257 CssmSubserviceUid(const CSSM_SUBSERVICE_UID
&rSSuid
) { memcpy(this, &rSSuid
, sizeof(*this)); }
259 CssmSubserviceUid
&operator = (const CSSM_SUBSERVICE_UID
&rSSuid
)
260 { memcpy(this, &rSSuid
, sizeof(CSSM_SUBSERVICE_UID
)); return *this; }
262 bool operator == (const CSSM_SUBSERVICE_UID
&other
) const
263 { return (this == &other
) || !memcmp(this, &other
, sizeof(CSSM_SUBSERVICE_UID
)); }
264 bool operator != (const CSSM_SUBSERVICE_UID
&other
) const
265 { return (this != &other
) && memcmp(this, &other
, sizeof(CSSM_SUBSERVICE_UID
)); }
266 bool operator < (const CSSM_SUBSERVICE_UID
&other
) const
267 { return memcmp(this, &other
, sizeof(CSSM_SUBSERVICE_UID
)) < 0; }
269 CssmSubserviceUid(const CSSM_GUID
&guid
, const CSSM_VERSION
*version
= NULL
,
270 uint32 subserviceId
= 0,
271 CSSM_SERVICE_TYPE subserviceType
= CSSM_SERVICE_DL
)
273 Guid
=guid
;SubserviceId
=subserviceId
;SubserviceType
=subserviceType
;
277 { Version
.Major
=0; Version
.Minor
=0; }
280 const ::Guid
&guid() const { return ::Guid::overlay(Guid
); }
281 uint32
subserviceId() const { return SubserviceId
; }
282 CSSM_SERVICE_TYPE
subserviceType() const { return SubserviceType
; }
283 CSSM_VERSION
version() const { return Version
; }
288 // User-friendlier CSSM_DATA thingies.
289 // CssmData is a PODWrapper and has no memory allocation features.
291 class CssmData
: public PodWrapper
<CssmData
, CSSM_DATA
> {
293 CssmData() { Data
= 0; Length
= 0; }
295 size_t length() const { return Length
; }
296 void *data() const { return Data
; }
297 void *end() const { return Data
+ Length
; }
300 // Create a CssmData from any pointer-to-byte-sized-object and length.
302 CssmData(void *data
, size_t length
)
303 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
304 CssmData(char *data
, size_t length
)
305 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
306 CssmData(unsigned char *data
, size_t length
)
307 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
308 CssmData(signed char *data
, size_t length
)
309 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
311 // the void * form accepts too much; explicitly deny all other types
312 private: template <class T
> CssmData(T
*, size_t); public:
315 // Do allow generic "wrapping" of any data structure, but make it conspicuous
316 // since it's not necessarily the Right Thing (alignment and byte order wise).
317 // Also note that the T & form removes const-ness, since there is no ConstCssmData.
320 static CssmData
wrap(const T
&it
)
321 { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it
)), sizeof(it
)); }
324 static CssmData
wrap(T
*data
, size_t length
)
325 { return CssmData(static_cast<void *>(data
), length
); }
328 // Automatically convert a CssmData to any pointer-to-byte-sized-type.
330 operator signed char * () const { return reinterpret_cast<signed char *>(Data
); }
331 operator unsigned char * () const { return reinterpret_cast<unsigned char *>(Data
); }
332 operator char * () const { return reinterpret_cast<char *>(Data
); }
333 operator void * () const { return reinterpret_cast<void *>(Data
); }
336 // If you want to interprete the contents of a CssmData blob as a particular
337 // type, you have to be more explicit to show that you know what you're doing.
341 T
*interpretedAs() const { return reinterpret_cast<T
*>(Data
); }
344 T
*interpretedAs(size_t len
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
) const
346 if (length() != len
) CssmError::throwMe(error
);
347 return interpretedAs
<T
>();
351 void length(size_t newLength
) // shorten only
352 { assert(newLength
<= Length
); Length
= newLength
; }
354 void *at(off_t offset
) const
355 { assert(offset
>= 0 && offset
<= Length
); return Data
+ offset
; }
356 void *at(off_t offset
, size_t size
) const // length-checking version
357 { assert(offset
>= 0 && offset
+ size
<= Length
); return Data
+ offset
; }
359 unsigned char operator [] (size_t pos
) const
360 { assert(pos
< Length
); return Data
[pos
]; }
361 void *use(size_t taken
) // logically remove some bytes
362 { assert(taken
<= Length
); void *r
= Data
; Length
-= taken
; Data
+= taken
; return r
; }
365 { Data
= NULL
; Length
= 0; }
367 operator string () const // convert to string type (no trailing null)
368 { return string(reinterpret_cast<const char *>(data()), length()); }
370 operator bool () const { return Data
!= NULL
; }
371 bool operator ! () const { return Data
== NULL
; }
372 bool operator < (const CssmData
&other
) const;
373 bool operator == (const CssmData
&other
) const
374 { return length() == other
.length() && !memcmp(data(), other
.data(), length()); }
375 bool operator != (const CssmData
&other
) const
376 { return !(*this == other
); }
378 // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you.
380 void extract(T
&destination
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
) const
382 if (length() != sizeof(destination
) || data() == NULL
)
383 CssmError::throwMe(error
);
384 memcpy(&destination
, data(), sizeof(destination
));
389 inline bool CssmData::operator < (const CssmData
&other
) const
391 if (Length
!= other
.Length
) // If lengths are not equal the shorter data is smaller.
392 return Length
< other
.Length
;
393 if (Length
== 0) // If lengths are both zero ignore the Data.
395 if (Data
== NULL
|| other
.Data
== NULL
) // arbitrary (but consistent) ordering
396 return Data
< other
.Data
;
397 return memcmp(Data
, other
.Data
, Length
) < 0; // Do a lexicographic compare on equal sized Data.
402 // User-friendler CSSM_CRYPTO_DATA objects
404 class CryptoCallback
{
406 CryptoCallback(CSSM_CALLBACK func
, void *ctx
= NULL
) : mFunction(func
), mCtx(ctx
) { }
407 CSSM_CALLBACK
function() const { return mFunction
; }
408 void *context() const { return mCtx
; }
410 CssmData
operator () () const
413 if (CSSM_RETURN err
= mFunction(&output
, mCtx
))
414 CssmError::throwMe(err
);
419 CSSM_CALLBACK mFunction
;
423 class CssmCryptoData
: public PodWrapper
<CssmCryptoData
, CSSM_CRYPTO_DATA
> {
427 CssmCryptoData(const CssmData
¶m
, CSSM_CALLBACK callback
= NULL
, void *ctx
= NULL
)
428 { Param
= const_cast<CssmData
&>(param
); Callback
= callback
; CallerCtx
= ctx
; }
430 CssmCryptoData(const CssmData
¶m
, CryptoCallback
&cb
)
431 { Param
= const_cast<CssmData
&>(param
); Callback
= cb
.function(); CallerCtx
= cb
.context(); }
433 CssmCryptoData(CSSM_CALLBACK callback
, void *ctx
= NULL
)
434 { /* ignore Param */ Callback
= callback
; CallerCtx
= ctx
; }
436 explicit CssmCryptoData(CryptoCallback
&cb
)
437 { /* ignore Param */ Callback
= cb
.function(); CallerCtx
= cb
.context(); }
440 CssmData
¶m() { return CssmData::overlay(Param
); }
441 const CssmData
¶m() const { return CssmData::overlay(Param
); }
442 bool hasCallback() const { return Callback
!= NULL
; }
443 CryptoCallback
callback() const { return CryptoCallback(Callback
, CallerCtx
); }
445 // get the value, whichever way is appropriate
446 CssmData
operator () () const
447 { return hasCallback() ? callback() () : param(); }
450 // a CssmCryptoContext whose callback is a virtual class member
451 class CryptoDataClass
: public CssmCryptoData
{
453 CryptoDataClass() : CssmCryptoData(callbackShim
, this) { }
454 virtual ~CryptoDataClass();
457 virtual CssmData
yield() = 0; // must subclass and implement this
460 static CSSM_RETURN
callbackShim(CSSM_DATA
*output
, void *ctx
)
463 *output
= reinterpret_cast<CryptoDataClass
*>(ctx
)->yield();
470 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
472 typedef CssmData CssmOid
;
476 // User-friendlier CSSM_KEY objects
478 class CssmKey
: public PodWrapper
<CssmKey
, CSSM_KEY
> {
480 CssmKey() { KeyHeader
.HeaderVersion
= CSSM_KEYHEADER_VERSION
; }
481 CssmKey(CSSM_KEY
&key
);
482 CssmKey(CSSM_DATA
&keyData
);
483 CssmKey(uint32 length
, uint8
*data
);
486 class Header
: public PodWrapper
<Header
, CSSM_KEYHEADER
> {
488 // access to components of the key header
489 CSSM_KEYBLOB_TYPE
blobType() const { return BlobType
; }
490 void blobType(CSSM_KEYBLOB_TYPE blobType
) { BlobType
= blobType
; }
492 CSSM_KEYBLOB_FORMAT
blobFormat() const { return Format
; }
493 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { Format
= blobFormat
; }
495 CSSM_KEYCLASS
keyClass() const { return KeyClass
; }
496 void keyClass(CSSM_KEYCLASS keyClass
) { KeyClass
= keyClass
; }
498 CSSM_KEY_TYPE
algorithm() const { return AlgorithmId
; }
499 void algorithm(CSSM_KEY_TYPE algorithm
) { AlgorithmId
= algorithm
; }
501 CSSM_KEY_TYPE
wrapAlgorithm() const { return WrapAlgorithmId
; }
502 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { WrapAlgorithmId
= wrapAlgorithm
; }
504 CSSM_ENCRYPT_MODE
wrapMode() const { return WrapMode
; }
505 void wrapMode(CSSM_ENCRYPT_MODE mode
) { WrapMode
= mode
; }
507 bool isWrapped() const { return WrapAlgorithmId
!= CSSM_ALGID_NONE
; }
509 const Guid
&cspGuid() const { return Guid::overlay(CspId
); }
510 void cspGuid(const Guid
&guid
) { Guid::overlay(CspId
) = guid
; }
512 uint32
attributes() const { return KeyAttr
; }
513 bool attribute(uint32 attr
) const { return KeyAttr
& attr
; }
514 void setAttribute(uint32 attr
) { KeyAttr
|= attr
; }
515 void clearAttribute(uint32 attr
) { KeyAttr
&= ~attr
; }
517 uint32
usage() const { return KeyUsage
; }
518 bool useFor(uint32 u
) const { return KeyUsage
& u
; }
520 void usage(uint32 u
) { KeyUsage
|= u
; }
521 void clearUsage(uint32 u
) { u
&= ~u
; }
525 // access to the key header
526 Header
&header() { return Header::overlay(KeyHeader
); }
527 const Header
&header() const { return Header::overlay(KeyHeader
); }
529 CSSM_KEYBLOB_TYPE
blobType() const { return header().blobType(); }
530 void blobType(CSSM_KEYBLOB_TYPE blobType
) { header().blobType(blobType
); }
532 CSSM_KEYBLOB_FORMAT
blobFormat() const { return header().blobFormat(); }
533 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { header().blobFormat(blobFormat
); }
535 CSSM_KEYCLASS
keyClass() const { return header().keyClass(); }
536 void keyClass(CSSM_KEYCLASS keyClass
) { header().keyClass(keyClass
); }
538 CSSM_KEY_TYPE
algorithm() const { return header().algorithm(); }
539 void algorithm(CSSM_KEY_TYPE algorithm
) { header().algorithm(algorithm
); }
541 CSSM_KEY_TYPE
wrapAlgorithm() const { return header().wrapAlgorithm(); }
542 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { header().wrapAlgorithm(wrapAlgorithm
); }
544 CSSM_ENCRYPT_MODE
wrapMode() const { return header().wrapMode(); }
545 void wrapMode(CSSM_ENCRYPT_MODE mode
) { header().wrapMode(mode
); }
547 bool isWrapped() const { return header().isWrapped(); }
548 const Guid
&cspGuid() const { return header().cspGuid(); }
550 uint32
attributes() const { return header().attributes(); }
551 bool attribute(uint32 a
) const { return header().attribute(a
); }
552 void setAttribute(uint32 attr
) { header().setAttribute(attr
); }
553 void clearAttribute(uint32 attr
) { header().clearAttribute(attr
); }
555 uint32
usage() const { return header().usage(); }
556 bool useFor(uint32 u
) const { return header().useFor(u
); }
558 void usage(uint32 u
) { header().usage(u
); }
559 void clearUsage(uint32 u
) { header().clearUsage(u
); }
562 // access to the key data
563 size_t length() const { return KeyData
.Length
; }
564 void *data() const { return KeyData
.Data
; }
565 operator void * () const { return data(); }
566 operator CssmData
& () { return CssmData::overlay(KeyData
); }
567 operator const CssmData
& () const { return static_cast<const CssmData
&>(KeyData
); }
568 operator bool () const { return KeyData
.Data
!= NULL
; }
569 void operator = (const CssmData
&data
) { KeyData
= data
; }
574 // Wrapped keys are currently identically structured to normal keys.
575 // But perhaps in the future...
577 typedef CssmKey CssmWrappedKey
;
581 // Other PodWrappers for stuff that is barely useful...
583 class QuerySizeData
: public PodWrapper
<QuerySizeData
, CSSM_QUERY_SIZE_DATA
> {
585 QuerySizeData(uint32 in
) { SizeInputBlock
= in
; SizeOutputBlock
= 0; }
587 uint32
inputSize() const { return SizeInputBlock
; }
588 uint32
inputSize(uint32 size
) { return SizeInputBlock
= size
; }
589 uint32
outputSize() const { return SizeOutputBlock
; }
592 class CSPOperationalStatistics
:
593 public PodWrapper
<CSPOperationalStatistics
, CSSM_CSP_OPERATIONAL_STATISTICS
> {
599 // User-friendli(er) DL queries.
600 // @@@ Preliminary (flesh out as needed)
602 class DLQuery
: public PodWrapper
<DLQuery
, CSSM_QUERY
> {
604 DLQuery() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
605 DLQuery(const CSSM_QUERY
&q
) { memcpy(this, &q
, sizeof(*this)); }
607 DLQuery
&operator = (const CSSM_QUERY
&q
)
608 { memcpy(this, &q
, sizeof(*this)); return *this; }
613 // CoreFoundation support.
614 // This will move into a separate file.
618 // Initialize-only self-releasing CF object handler (lightweight).
619 // Does not support assignment.
621 template <class CFType
> class CFRef
{
623 CFRef() : mRef(NULL
) { }
624 CFRef(CFType ref
) : mRef(ref
) { }
625 CFRef(const CFRef
&ref
) : mRef(ref
) { if (ref
) CFRetain(ref
); }
626 ~CFRef() { if (mRef
) CFRelease(mRef
); }
628 CFRef
&operator = (CFType ref
)
629 { if (ref
) CFRetain(ref
); if (mRef
) CFRelease(mRef
); mRef
= ref
; return *this; }
631 operator CFType () const { return mRef
; }
632 operator bool () const { return mRef
!= NULL
; }
633 bool operator ! () const { return mRef
== NULL
; }
639 template <class CFType
> class CFCopyRef
{
641 CFCopyRef() : mRef(NULL
) { }
642 explicit CFCopyRef(CFType ref
) : mRef(ref
) { if (ref
) CFRetain(ref
); }
643 CFCopyRef(const CFCopyRef
&ref
) : mRef(ref
) { if (ref
) CFRetain(ref
); }
644 ~CFCopyRef() { if (mRef
) CFRelease(mRef
); }
646 CFCopyRef
&operator = (CFType ref
)
647 { if (ref
) CFRetain(ref
); if (mRef
) CFRelease(mRef
); mRef
= ref
; return *this; }
649 operator CFType () const { return mRef
; }
650 operator bool () const { return mRef
!= NULL
; }
651 bool operator ! () const { return mRef
== NULL
; }
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 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
;
743 } // end namespace Security
745 #ifdef _CPP_UTILITIES
749 #endif //_H_UTILITIES