]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/utilities.h
Security-30.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / utilities.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 /*
20 * cssm utilities
21 */
22 #ifndef _H_UTILITIES
23 #define _H_UTILITIES
24
25 #include <Security/cssm.h>
26 #include <Security/utility_config.h>
27 #include <exception>
28 #include <new>
29 #include <string>
30 #include <errno.h>
31 #include <string.h>
32
33 #ifdef _CPP_UTILITIES
34 #pragma export on
35 #endif
36
37 namespace Security
38 {
39
40 //
41 // Elementary debugging support.
42 // #include <debugging.h> for more debugging facilities.
43 //
44 #if defined(NDEBUG)
45
46 # define safe_cast static_cast
47 # define safer_cast static_cast
48
49 # define IFDEBUG(it) /* do nothing */
50 # define IFNDEBUG(it) it
51
52 #else
53
54 template <class Derived, class Base>
55 inline Derived safer_cast(Base &base)
56 {
57 return dynamic_cast<Derived>(base);
58 }
59
60 template <class Derived, class Base>
61 inline Derived safe_cast(Base *base)
62 {
63 if (base == NULL)
64 return NULL; // okay to cast NULL to NULL
65 Derived p = dynamic_cast<Derived>(base);
66 assert(p);
67 return p;
68 }
69
70 # define IFDEBUG(it) it
71 # define IFNDEBUG(it) /* do nothing */
72
73 #endif //NDEBUG
74
75
76 //
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.
81 //
82 #define NOCOPY(Type) private: Type(const Type &); void operator = (const Type &);
83
84
85 //
86 // Exception hierarchy
87 //
88 class CssmCommonError : public exception {
89 protected:
90 CssmCommonError();
91 CssmCommonError(const CssmCommonError &source);
92 public:
93 virtual ~CssmCommonError();
94
95 virtual CSSM_RETURN cssmError() const = 0;
96 virtual CSSM_RETURN cssmError(CSSM_RETURN base) const;
97 virtual OSStatus osStatus() const;
98 };
99
100 class CssmError : public CssmCommonError {
101 protected:
102 CssmError(CSSM_RETURN err);
103 public:
104 const CSSM_RETURN error;
105 virtual CSSM_RETURN cssmError() const;
106 virtual OSStatus osStatus() const;
107 virtual const char *what () const;
108
109 static CSSM_RETURN merge(CSSM_RETURN error, CSSM_RETURN base);
110
111 static void throwMe(CSSM_RETURN error) __attribute__((noreturn));
112 };
113
114 class UnixError : public CssmCommonError {
115 protected:
116 UnixError();
117 UnixError(int err);
118 public:
119 const int error;
120 virtual CSSM_RETURN cssmError() const;
121 virtual OSStatus osStatus() const;
122 virtual const char *what () const;
123
124 static void check(int result) { if (result == -1) throwMe(); }
125 static void throwMe(int err = errno) __attribute__((noreturn));
126
127 // @@@ This is a hack for the Network protocol state machine
128 static UnixError make(int err = errno);
129 };
130
131 class MacOSError : public CssmCommonError {
132 protected:
133 MacOSError(int err);
134 public:
135 const int error;
136 virtual CSSM_RETURN cssmError() const;
137 virtual OSStatus osStatus() const;
138 virtual const char *what () const;
139
140 static void check(OSStatus status) { if (status != noErr) throwMe(status); }
141 static void throwMe(int err) __attribute__((noreturn));
142 };
143
144
145 //
146 // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions.
147 // Usage:
148 // BEGIN_API
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
154 //
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); } \
160 return CSSM_OK;
161 #define END_API0 } catch (...) { return; }
162 #define END_API1(bad) } catch (...) { return bad; }
163
164
165 //
166 // Helpers for memory pointer validation
167 //
168 template <class T>
169 inline T &Required(T *ptr, CSSM_RETURN err = CSSM_ERRCODE_INVALID_POINTER)
170 {
171 if (ptr == NULL)
172 CssmError::throwMe(err);
173 return *ptr;
174 }
175
176
177 //
178 // Tools to build POD wrapper classes
179 //
180 template <class Wrapper, class POD>
181 class PodWrapper : public POD {
182 public:
183 // pure typecasts
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); }
188
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); }
197
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); }
207 };
208
209
210 //
211 // Template builder support
212 //
213 template <class T>
214 struct Nonconst {
215 typedef T Type;
216 };
217
218 template <class U>
219 struct Nonconst<const U> {
220 typedef U Type;
221 };
222
223
224 //
225 // User-friendly GUIDs
226 //
227 class Guid : public PodWrapper<Guid, CSSM_GUID> {
228 public:
229 Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
230 Guid(const CSSM_GUID &rGuid) { memcpy(this, &rGuid, sizeof(*this)); }
231
232 Guid &operator = (const CSSM_GUID &rGuid)
233 { memcpy(this, &rGuid, sizeof(CSSM_GUID)); return *this; }
234
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;
243 }
244
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);
248 };
249
250
251 //
252 // User-friendly CSSM_SUBSERVICE_UIDs
253 //
254 class CssmSubserviceUid : public PodWrapper<CssmSubserviceUid, CSSM_SUBSERVICE_UID> {
255 public:
256 CssmSubserviceUid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
257 CssmSubserviceUid(const CSSM_SUBSERVICE_UID &rSSuid) { memcpy(this, &rSSuid, sizeof(*this)); }
258
259 CssmSubserviceUid &operator = (const CSSM_SUBSERVICE_UID &rSSuid)
260 { memcpy(this, &rSSuid, sizeof(CSSM_SUBSERVICE_UID)); return *this; }
261
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; }
268
269 CssmSubserviceUid(const CSSM_GUID &guid, const CSSM_VERSION *version = NULL,
270 uint32 subserviceId = 0,
271 CSSM_SERVICE_TYPE subserviceType = CSSM_SERVICE_DL)
272 {
273 Guid=guid;SubserviceId=subserviceId;SubserviceType=subserviceType;
274 if (version)
275 Version=*version;
276 else
277 { Version.Major=0; Version.Minor=0; }
278 }
279
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; }
284 };
285
286
287 //
288 // User-friendlier CSSM_DATA thingies.
289 // CssmData is a PODWrapper and has no memory allocation features.
290 //
291 class CssmData : public PodWrapper<CssmData, CSSM_DATA> {
292 public:
293 CssmData() { Data = 0; Length = 0; }
294
295 size_t length() const { return Length; }
296 void *data() const { return Data; }
297 void *end() const { return Data + Length; }
298
299 //
300 // Create a CssmData from any pointer-to-byte-sized-object and length.
301 //
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; }
310
311 // the void * form accepts too much; explicitly deny all other types
312 private: template <class T> CssmData(T *, size_t); public:
313
314 //
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.
318 //
319 template <class T>
320 static CssmData wrap(const T &it)
321 { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it)), sizeof(it)); }
322
323 template <class T>
324 static CssmData wrap(T *data, size_t length)
325 { return CssmData(static_cast<void *>(data), length); }
326
327 //
328 // Automatically convert a CssmData to any pointer-to-byte-sized-type.
329 //
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); }
334
335 //
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.
338 // See wrap() above.
339 //
340 template <class T>
341 T *interpretedAs() const { return reinterpret_cast<T *>(Data); }
342
343 template <class T>
344 T *interpretedAs(size_t len, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) const
345 {
346 if (length() != len) CssmError::throwMe(error);
347 return interpretedAs<T>();
348 }
349
350 public:
351 void length(size_t newLength) // shorten only
352 { assert(newLength <= Length); Length = newLength; }
353
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; }
358
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; }
363
364 void clear()
365 { Data = NULL; Length = 0; }
366
367 operator string () const // convert to string type (no trailing null)
368 { return string(reinterpret_cast<const char *>(data()), length()); }
369
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); }
377
378 // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you.
379 template <class T>
380 void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) const
381 {
382 if (length() != sizeof(destination) || data() == NULL)
383 CssmError::throwMe(error);
384 memcpy(&destination, data(), sizeof(destination));
385 }
386 };
387
388
389 inline bool CssmData::operator < (const CssmData &other) const
390 {
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.
394 return false;
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.
398 }
399
400
401 //
402 // User-friendler CSSM_CRYPTO_DATA objects
403 //
404 class CryptoCallback {
405 public:
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; }
409
410 CssmData operator () () const
411 {
412 CssmData output;
413 if (CSSM_RETURN err = mFunction(&output, mCtx))
414 CssmError::throwMe(err);
415 return output;
416 }
417
418 private:
419 CSSM_CALLBACK mFunction;
420 void *mCtx;
421 };
422
423 class CssmCryptoData : public PodWrapper<CssmCryptoData, CSSM_CRYPTO_DATA> {
424 public:
425 CssmCryptoData() { }
426
427 CssmCryptoData(const CssmData &param, CSSM_CALLBACK callback = NULL, void *ctx = NULL)
428 { Param = const_cast<CssmData &>(param); Callback = callback; CallerCtx = ctx; }
429
430 CssmCryptoData(const CssmData &param, CryptoCallback &cb)
431 { Param = const_cast<CssmData &>(param); Callback = cb.function(); CallerCtx = cb.context(); }
432
433 CssmCryptoData(CSSM_CALLBACK callback, void *ctx = NULL)
434 { /* ignore Param */ Callback = callback; CallerCtx = ctx; }
435
436 explicit CssmCryptoData(CryptoCallback &cb)
437 { /* ignore Param */ Callback = cb.function(); CallerCtx = cb.context(); }
438
439 // member access
440 CssmData &param() { return CssmData::overlay(Param); }
441 const CssmData &param() const { return CssmData::overlay(Param); }
442 bool hasCallback() const { return Callback != NULL; }
443 CryptoCallback callback() const { return CryptoCallback(Callback, CallerCtx); }
444
445 // get the value, whichever way is appropriate
446 CssmData operator () () const
447 { return hasCallback() ? callback() () : param(); }
448 };
449
450 // a CssmCryptoContext whose callback is a virtual class member
451 class CryptoDataClass : public CssmCryptoData {
452 public:
453 CryptoDataClass() : CssmCryptoData(callbackShim, this) { }
454 virtual ~CryptoDataClass();
455
456 protected:
457 virtual CssmData yield() = 0; // must subclass and implement this
458
459 private:
460 static CSSM_RETURN callbackShim(CSSM_DATA *output, void *ctx)
461 {
462 BEGIN_API
463 *output = reinterpret_cast<CryptoDataClass *>(ctx)->yield();
464 END_API(CSSM)
465 }
466 };
467
468
469 //
470 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
471 //
472 typedef CssmData CssmOid;
473
474
475 //
476 // User-friendlier CSSM_KEY objects
477 //
478 class CssmKey : public PodWrapper<CssmKey, CSSM_KEY> {
479 public:
480 CssmKey() { KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; }
481 CssmKey(CSSM_KEY &key);
482 CssmKey(CSSM_DATA &keyData);
483 CssmKey(uint32 length, uint8 *data);
484
485 public:
486 class Header : public PodWrapper<Header, CSSM_KEYHEADER> {
487 public:
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; }
491
492 CSSM_KEYBLOB_FORMAT blobFormat() const { return Format; }
493 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat) { Format = blobFormat; }
494
495 CSSM_KEYCLASS keyClass() const { return KeyClass; }
496 void keyClass(CSSM_KEYCLASS keyClass) { KeyClass = keyClass; }
497
498 CSSM_KEY_TYPE algorithm() const { return AlgorithmId; }
499 void algorithm(CSSM_KEY_TYPE algorithm) { AlgorithmId = algorithm; }
500
501 CSSM_KEY_TYPE wrapAlgorithm() const { return WrapAlgorithmId; }
502 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm) { WrapAlgorithmId = wrapAlgorithm; }
503
504 CSSM_ENCRYPT_MODE wrapMode() const { return WrapMode; }
505 void wrapMode(CSSM_ENCRYPT_MODE mode) { WrapMode = mode; }
506
507 bool isWrapped() const { return WrapAlgorithmId != CSSM_ALGID_NONE; }
508
509 const Guid &cspGuid() const { return Guid::overlay(CspId); }
510 void cspGuid(const Guid &guid) { Guid::overlay(CspId) = guid; }
511
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; }
516
517 uint32 usage() const { return KeyUsage; }
518 bool useFor(uint32 u) const { return KeyUsage & u; }
519
520 void usage(uint32 u) { KeyUsage |= u; }
521 void clearUsage(uint32 u) { u &= ~u; }
522
523 };
524
525 // access to the key header
526 Header &header() { return Header::overlay(KeyHeader); }
527 const Header &header() const { return Header::overlay(KeyHeader); }
528
529 CSSM_KEYBLOB_TYPE blobType() const { return header().blobType(); }
530 void blobType(CSSM_KEYBLOB_TYPE blobType) { header().blobType(blobType); }
531
532 CSSM_KEYBLOB_FORMAT blobFormat() const { return header().blobFormat(); }
533 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat) { header().blobFormat(blobFormat); }
534
535 CSSM_KEYCLASS keyClass() const { return header().keyClass(); }
536 void keyClass(CSSM_KEYCLASS keyClass) { header().keyClass(keyClass); }
537
538 CSSM_KEY_TYPE algorithm() const { return header().algorithm(); }
539 void algorithm(CSSM_KEY_TYPE algorithm) { header().algorithm(algorithm); }
540
541 CSSM_KEY_TYPE wrapAlgorithm() const { return header().wrapAlgorithm(); }
542 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm) { header().wrapAlgorithm(wrapAlgorithm); }
543
544 CSSM_ENCRYPT_MODE wrapMode() const { return header().wrapMode(); }
545 void wrapMode(CSSM_ENCRYPT_MODE mode) { header().wrapMode(mode); }
546
547 bool isWrapped() const { return header().isWrapped(); }
548 const Guid &cspGuid() const { return header().cspGuid(); }
549
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); }
554
555 uint32 usage() const { return header().usage(); }
556 bool useFor(uint32 u) const { return header().useFor(u); }
557
558 void usage(uint32 u) { header().usage(u); }
559 void clearUsage(uint32 u) { header().clearUsage(u); }
560
561 public:
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; }
570 };
571
572
573 //
574 // Wrapped keys are currently identically structured to normal keys.
575 // But perhaps in the future...
576 //
577 typedef CssmKey CssmWrappedKey;
578
579
580 //
581 // Other PodWrappers for stuff that is barely useful...
582 //
583 class QuerySizeData : public PodWrapper<QuerySizeData, CSSM_QUERY_SIZE_DATA> {
584 public:
585 QuerySizeData(uint32 in) { SizeInputBlock = in; SizeOutputBlock = 0; }
586
587 uint32 inputSize() const { return SizeInputBlock; }
588 uint32 inputSize(uint32 size) { return SizeInputBlock = size; }
589 uint32 outputSize() const { return SizeOutputBlock; }
590 };
591
592 class CSPOperationalStatistics :
593 public PodWrapper<CSPOperationalStatistics, CSSM_CSP_OPERATIONAL_STATISTICS> {
594 public:
595 };
596
597
598 //
599 // User-friendli(er) DL queries.
600 // @@@ Preliminary (flesh out as needed)
601 //
602 class DLQuery : public PodWrapper<DLQuery, CSSM_QUERY> {
603 public:
604 DLQuery() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; }
605 DLQuery(const CSSM_QUERY &q) { memcpy(this, &q, sizeof(*this)); }
606
607 DLQuery &operator = (const CSSM_QUERY &q)
608 { memcpy(this, &q, sizeof(*this)); return *this; }
609 };
610
611
612 //
613 // CoreFoundation support.
614 // This will move into a separate file.
615 //
616
617 //
618 // Initialize-only self-releasing CF object handler (lightweight).
619 // Does not support assignment.
620 //
621 template <class CFType> class CFRef {
622 public:
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); }
627
628 CFRef &operator = (CFType ref)
629 { if (ref) CFRetain(ref); if (mRef) CFRelease(mRef); mRef = ref; return *this; }
630
631 operator CFType () const { return mRef; }
632 operator bool () const { return mRef != NULL; }
633 bool operator ! () const { return mRef == NULL; }
634
635 private:
636 CFType mRef;
637 };
638
639 template <class CFType> class CFCopyRef {
640 public:
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); }
645
646 CFCopyRef &operator = (CFType ref)
647 { if (ref) CFRetain(ref); if (mRef) CFRelease(mRef); mRef = ref; return *this; }
648
649 operator CFType () const { return mRef; }
650 operator bool () const { return mRef != NULL; }
651 bool operator ! () const { return mRef == NULL; }
652
653 private:
654 CFType mRef;
655 };
656
657 // Help with container of something->pointer cleanup
658 template <class In>
659 static inline void for_each_delete(In first, In last)
660 {
661 while (first != last)
662 delete *(first++);
663 }
664
665 // Help with map of something->pointer cleanup
666 template <class In>
667 static inline void for_each_map_delete(In first, In last)
668 {
669 while (first != last)
670 delete (first++)->second;
671 }
672
673 // Quick and dirty template for a (temporary) array of something
674 // Usage example auto_array<uint32> anArray(20);
675 template <class T>
676 class auto_array
677 {
678 public:
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; }
686 private:
687 T *mArray;
688 };
689
690 // Template for a vector-like class that takes a c-array as it's
691 // underlying storage without making a copy.
692 template <class _Tp>
693 class constVector
694 {
695 NOCOPY(constVector<_Tp>)
696 public:
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;
703
704 typedef reverse_iterator<const_iterator> const_reverse_iterator;
705 public:
706 const_iterator begin() const { return _M_start; }
707 const_iterator end() const { return _M_finish; }
708
709 const_reverse_iterator rbegin() const
710 { return const_reverse_iterator(end()); }
711 const_reverse_iterator rend() const
712 { return const_reverse_iterator(begin()); }
713
714 size_type size() const
715 { return size_type(end() - begin()); }
716 bool empty() const
717 { return begin() == end(); }
718
719 const_reference operator[](size_type __n) const { return *(begin() + __n); }
720
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]; }
724
725 constVector(size_type __n, const _Tp* __value)
726 : _M_start(__value), _M_finish(__value + __n)
727 {}
728
729 constVector() : _M_start(NULL), _M_finish(NULL) {}
730
731 void overlay(size_type __n, const _Tp* __value) {
732 _M_start = __value;
733 _M_finish = __value + __n;
734 }
735
736 const_reference front() const { return *begin(); }
737 const_reference back() const { return *(end() - 1); }
738 private:
739 const _Tp *_M_start;
740 const _Tp *_M_finish;
741 };
742
743 } // end namespace Security
744
745 #ifdef _CPP_UTILITIES
746 #pragma export off
747 #endif
748
749 #endif //_H_UTILITIES