Objective-C++ Preprocessor  5.0 with ARC & GC
C++ classes to enhance syntax and manage reference counting.
objvec.h
Go to the documentation of this file.
1 /*
2  * objvec.h - varaiable length storage classes for Objective-C
3  * ========
4  *
5  * Created by John Holdsworth on 01/04/2009.
6  * Copyright 2009 © John Holdsworth. All Rights Reserved.
7  *
8  * $Id: //depot/ObjCpp/objvec.h#31 $
9  * $DateTime: 2013/12/30 21:08:22 $
10  *
11  * C++ classes to wrap up XCode classes for operator overload of
12  * useful operations such as access to NSArrays and NSDictionary
13  * by subscript or NSString operators such as + for concatenation.
14  *
15  * This works as the Apple Objective-C compiler supports source
16  * which mixes C++ with objective C. To enable this: for each
17  * source file which will include/import this header file, select
18  * it in Xcode and open it's "Info". To enable mixed compilation,
19  * for the file's "File Type" select: "sourcecode.cpp.objcpp".
20  *
21  * For bugs or ommisions please email objcpp@johnholdsworth.com
22  *
23  * Home page for updates and docs: http://objcpp.johnholdsworth.com
24  *
25  * If you find it useful please send a donation via paypal to account
26  * objcpp@johnholdsworth.com. Thanks.
27  *
28  * License
29  * =======
30  *
31  * You may make commercial use of this source in applications without
32  * charge but not sell it as source nor can you remove this notice from
33  * this source if you redistribute. You can make any changes you like
34  * to this code before redistribution but you must annotate them below.
35  *
36  * For further details http://objcpp.johnholdsworth.com/license.html
37  *
38  * THIS CODE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND EITHER
39  * EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
41  *
42  * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
43  * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
44  * THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
45  * ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT
46  * OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
47  * TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED
48  * BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH
49  * ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
50  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
51  *
52  */
53 
54 #ifndef _objvec_h_
55 #define _objvec_h_
56 #ifdef __cplusplus
57 #import "objcpp.h"
58 
59 static struct { int buffered; } _objvec;
60 
61 /*====================================================================================*/
62 /*============================== Variable length buffer===============================*/
63 
64 /**
65  Internal class to allocate storage on demand as it is accessed by ref using the
66  subscript operator. A memory is allocated and reallocated if the element type is a
67  plain type it will be zeroed out otherwise if it is a class the constructor will
68  be called for each element in the array as it is allocated. On reallocation a new
69  oversized array is allocated then the "=" operator used to copy the old values
70  to the new array. This operator should "steal" any deep _refs from the old
71  instance before it is destructed as does the OOBuffer class itself as it is used
72  recursively.
73 
74  Usage:
75  <pre>
76  OOBuffer<OOBuffer<double> > x; // not ref counted however
77  // and can not be put into arrays or dictionaries
78  x[99][99] = 43;
79  </pre>
80  */
81 
82 template <typename ETYPE>
83 class OOBuffer {
84  ETYPE *buff;
85 
86  void realloc( NSUInteger size ) {
87  ETYPE *next = new ETYPE[size];
88  const char *info = @encode(ETYPE);
89  if ( info[0] != '{' )
90  memset( next, '\000', size * sizeof *next );
91  OOTrace( @"0x%08lx %s [%lu] 0x%08lx = 0x%08lx %s",
92  (OOAddress)this, "BREALLOC", (OOLong)size, (OOAddress)buff, (OOAddress)next, info );
93  if ( buff ) {
94  for ( int i=0 ; i<allocated ; i++ )
95  next[i] = buff[i];
96  delete[] buff;
97  }
98  allocated = size;
99  buff = next;
100  }
101 
102 public:
103  NSUInteger used, allocated, bounds;
104 
106  _objvec.buffered++;
107  buff = NULL;
108  used = allocated = bounds = 0;
109  OOTrace( @"0x%08lx %s", (OOAddress)this, "BCONSTRUCT" );
110  }
111  oo_inline OOBuffer( NSUInteger size ) {
112  _objvec.buffered++;
113  buff = NULL;
114  realloc( bounds = size );
115  used = 0;
116  OOTrace( @"0x%08lx %s [%ld] 0x%08lx", (OOAddress)this, "BCONSTRUCT", (OOLong)size, (OOAddress)buff );
117  }
118  oo_inline ETYPE &operator [] ( NSInteger sub ) {
119  // reallocate?
120  if ( !buff || sub+1 > allocated )
121  realloc( (sub+11)*4/3 );
122 
123  // update elements used
124  if ( used < sub+1 )
125  used = sub+1;
126  else if ( sub < 0 )
127  sub += bounds ? bounds : used;
128  else if ( bounds && sub+1 > bounds )
129  OOWarn( @"0x%08lx Subscript [%ld] beyond bounds of array (%ld)", (OOAddress)this, (OOLong)sub, (OOLong)bounds );
130  return buff[sub];
131  }
132 
133  // steal pointer to contents when copied on reallocate of parent
135  OOTrace( @"0x%08lx %s, 0x%08lx = 0x%08lx", (OOAddress)this, "BASSIGN", (OOAddress)buff, (OOAddress)from.buff );
136  buff = from.buff;
137  used = from.used;
138  allocated = from.allocated;
139  bounds = from.bounds;
140  from.buff = NULL;
141  return *this;
142  }
144  _objvec.buffered--;
145  if( buff ) {
146  OOTrace( @"0x%08lx %s 0x%08lx", (OOAddress)this, "BDESTRUCT", (OOAddress)buff );
147  delete[] buff;
148  }
149  }
150 };
151 
152 /*====================================================================================*/
153 /*============================== Pointer classes =====================================*/
154 
155 /**
156  OOPointer subclass to store a pointer to a heap allocated C++ class instance
157  inside an NSValue object to it can be ref counted and stored in OSX
158  buffs such as NSMutableDictionary.
159 
160  Usage:
161  <pre>
162  OOClassPtr<aclass> avar = new aclass();
163  OODictionary<OOClassPtr<aclass>> a dict;
164  dict[@"KEY"] = avar;
165  ~avar;
166  ~dict[@"KEY"]; // instance deleted here
167  </pre>
168  */
169 
170 #ifdef OO_ARC
171 template <typename CNAME>
172 class OOClassCtr {
173 public:
174  CNAME *ptr;
175  unsigned ctr;
176  OOClassCtr( CNAME *ptr ) {
177  this->ptr = ptr;
178  this->ctr = 1;
179  }
180  ~OOClassCtr() {
181  delete this->ptr;
182  }
183 };
184 #endif
185 
186 template <typename CNAME>
187 #ifdef OO_ARC
188 class OOClassPtr : public OOPointer<OOClassCtr<CNAME> *> {
189 #else
190 class OOClassPtr : public OOPointer<CNAME *> {
191 #endif
192  oo_inline CNAME &calloc() {
193  if ( !this->pget() ) {
194  OOTrace( @"0x%08lx %s", (OOAddress)this, "CALLOC" );
195  cset( new CNAME() );
196  }
197 #ifdef OO_ARC
198  return *this->pget()->ptr;
199 #else
200  return *this->pget();
201 #endif
202  }
203  inline void replace( id val );
204 protected:
205  oo_inline NSValue *cset( NSValue *val ) OO_RETURNS {
206  replace( val );
207  return this->pset( val );
208  }
209  oo_inline CNAME &cset( CNAME *cptr ) {
210  replace( nil );
211 #ifdef OO_ARC
212  return *this->pset( new OOClassCtr<CNAME>( cptr ) )->ptr;
213 #else
214  return *this->pset( cptr );
215 #endif
216  }
217 public:
218  oo_inline OOClassPtr() {}
219  oo_inline OOClassPtr( CNAME *cptr ) { *this = cptr; }
220  oo_inline OOClassPtr( CNAME &cptr ) { *this = &cptr; }
221  oo_inline OOClassPtr( NSValue *val ) { *this = val; }
222  oo_inline OOClassPtr( const OOClassPtr &val ) { *this = val.get(); }
223  oo_inline OOClassPtr( id val, id next ) {
224  *this = val;
225  replace( next );
226  }
227  oo_inline ~OOClassPtr() { *this = OONil; }
228 
229  oo_inline OOClassPtr &operator = ( CNAME *cptr ) { cset( cptr ); return *this; }
230  oo_inline OOClassPtr &operator = ( CNAME &cptr ) { cset( &cptr ); return *this; }
231  oo_inline OOClassPtr &operator = ( NSValue *val ) { cset( val ); return *this; }
232  oo_inline OOClassPtr &operator = ( const OOClassPtr &val ) { cset( val.get() ); return *this; }
233 
234  oo_inline CNAME &cget() { return calloc(); }
235  oo_inline CNAME &operator * () { return calloc(); }
236 
237  oo_inline OOClassPtr<CNAME> operator ~ () {
238  OOClassPtr<CNAME> save = *this;
239  *this = OONil;
240  return save;
241  }
242 };
243 
244 /*===================================================================================*/
245 /*=============================== Storage classes ===================================*/
246 
247 /**
248  A more efficient buff class than NSArray for any element type (int, id, OOReference<NSString> etc.).
249  Memory is allocated on deamnd when _refd by the subscipt operator and if the type is a class
250  its constructors and destructors will be called by the underlying OOBuffer class.
251 
252  Usage:
253  <pre>
254  OOVector<double> array;
255  array[99] = 43.
256  OOVector<OOString> strarry;
257  array[99] = @"THIS";
258  </pre>
259  */
260 
261 template <typename ETYPE>
262 class OOVector : public OOClassPtr< OOBuffer<ETYPE> > {
263 public:
265  oo_inline OOVector( const OOVector &val ) { *this = val; }
266  ///oo_inline OOVector( OOClassPtr<OOVector<ETYPE> > &val ) { *this = val.cget(); }
267  oo_inline OOVector( int size ) { this->cset( new OOBuffer<ETYPE>( size ) ); }
269  int size = array;
270  this->cset( new OOBuffer<ETYPE>( size ) );
271  for ( int i=0 ; i<size ; i++ )
272  (*this)[i] = array[i];
273  }
274  oo_inline OOVector( const NSArray *array ) {
275  int size = [array count];
276  this->cset( new OOBuffer<ETYPE>( size ) );
277  for ( int i=0 ; i<size ; i++ )
278  (*this)[i] = [array objectAtIndex:i];
279  }
280 
281  oo_inline void reserve( NSUInteger size ) {
282  (*this)[size-1];
283  }
284  oo_inline NSUInteger size() {
285  return this->cget().used;
286  }
287  oo_inline ETYPE *begin() {
288  return size() ? &(*this)[0] : NULL;
289  }
290  oo_inline ETYPE *end() {
291  return begin()+size();
292  }
293 
294  oo_inline OOVector &operator = ( NSValue *val ) { this->cset( val ); return *this; }
295  oo_inline OOVector &operator = ( const OOVector &val ) { this->cset( val ); return *this; }
296 
297  oo_inline operator int () {
298  return size();
299  }
300  oo_inline ETYPE &operator [] ( int sub ) {
301  return this->cget()[ sub ];
302  }
303  oo_inline OOVector &operator += ( ETYPE value ) {
304  (*this)[this->cget().used] = value;
305  return *this;
306  }
307 };
308 
309 /**
310  A two dimensional Container class of any size using in effect a OOVector of OOBuffer instances.
311  */
312 
313 template <typename ETYPE>
314 class OOMatrix : public OOVector< OOBuffer<ETYPE> > {
315 public:
317  oo_inline OOMatrix( const OOMatrix &val ) { *this = val; }
318 
319  oo_inline OOMatrix &operator = ( NSValue *val ) { this->cset( val ); return *this; }
320  oo_inline OOMatrix &operator = ( const OOMatrix<ETYPE> &val ) { cset( val.get() ); return *this; }
321 };
322 
323 /**
324  A three dimensional Container class of any size using a OOVector of OOBuffers of OOBuffers.
325  */
326 
327 template <typename ETYPE>
328 class OOCube : public OOVector< OOBuffer< OOBuffer<ETYPE> > > {
329 public:
330  oo_inline OOCube() { }
331  oo_inline OOCube( const OOCube &val ) { *this = val; }
332  oo_inline OOCube &operator = ( NSValue *val ) { this->cset( val ); return *this; }
333  oo_inline OOCube &operator = ( const OOCube &val ) { cset( val.get() ); return *this; }
334 };
335 
336 /**
337  A faster NSMutableArray replacement that correctly ref counts and releases Objective-C objects.
338 
339  Usage:
340  <pre>
341  OOObjects<NSString *> var;
342  var[99] = @"THIS";
343  </pre>
344  */
345 
346 template <typename RTYPE>
347 class OOObjects : public OOVector<OOReference<RTYPE> > {
348 public:
350  oo_inline OOObjects( int size ) { this->cset( new OOBuffer< OOReference<RTYPE> >( size ) ); }
351  oo_inline OOObjects( const OOArray<RTYPE> array ) { *this = array.get(); }
352  oo_inline OOObjects( NSMutableArray *arr ) { *this = arr; }
353  oo_inline OOObjects( const OOObjects &val ) { *this = val; }
354 
355  oo_inline OOObjects &operator = ( const OOObjects &val ) { this->cset( val.get() ); return *this; }
356  oo_inline OOObjects &operator = ( NSValue *val ) { this->cset( val ); return *this; }
357  oo_inline OOObjects &operator = ( NSArray *array ) {
358  for ( int i=0 ; i<[array count] ; i++ )
359  (*this)[i] = [array objectAtIndex:i];
360  return *this;
361  }
362 
364  OOBuffer<OOReference<RTYPE> > &buff = this->cget();
365  int count = buff.bounds ? buff.bounds : buff.used;
366  OOArray<RTYPE> array( count );
367  for ( int i=0 ; i<count ; i++ )
368  array += buff[i];
369  return &array;
370  }
371  oo_inline operator OOArray<RTYPE> () { return array(); }
372  oo_inline operator NSArray * () OO_AUTORETURNS { return &array(); }
373 };
374 
375 /**
376  A fast container for an array of strings.
377  <pre>
378  OOStrings ted;
379  ted[99] <<= @"Go on ";
380  ted[99] *= 10;
381  </pre>
382  */
383 
384 class OOStrings : public OOVector<OOString> {
385 public:
387  oo_inline OOStrings( NSMutableArray *arr ) { *this = arr; }
388  oo_inline OOStrings( const OOStrings &val ) { *this = val; }
389  oo_inline OOStrings( cOOStringArray array ) { *this = array.get(); }
390 
391  oo_inline OOStrings &operator = ( const OOStrings &val ) { *this = val.get(); return *this; }
392  oo_inline OOStrings &operator = ( NSValue *val ) { this->cset( val ); return *this; }
393  oo_inline OOStrings &operator = ( NSArray *array ) {
394  for ( int i=0 ; i<[array count] ; i++ )
395  (*this)[i] = (NSMutableString *)[array objectAtIndex:i];
396  return *this;
397  }
398 
400  OOBuffer<OOString> &buff = this->cget();
401  NSUInteger count = buff.bounds ? buff.bounds : buff.used;
402  OOStringArray array( (int)count );
403  for ( int i=0 ; i<count ; i++ )
404  array += buff[i];
405  return &array;
406  }
407  oo_inline operator OOStringArray () { return array(); }
408  oo_inline operator NSArray * () OO_AUTORETURNS { return &array(); }
409 };
410 
411 template <typename CNAME>
412 class OOClassArray;
413 template <typename CNAME>
414 class OOArcDictSub;
415 
416 template <typename CNAME>
417 class OOArcArraySub : public OOArraySub<OOClassPtr<CNAME> > {
418  friend class OOClassArray<CNAME>;
419  friend class OOArcDictSub<CNAME>;
420 
421  oo_inline OOArcArraySub( OOClassArray<CNAME> *root, NSInteger idx ) :
422  OOArraySub<OOClassPtr<CNAME> >( root, idx ) {
423  }
424  oo_inline OOArcArraySub( OOArraySub<NSMutableArray *> *ref, NSInteger sub ) :
425  OOArraySub<OOClassPtr<CNAME> >( ref, sub ) {
426  }
427  oo_inline OOArcArraySub( OODictionarySub<NSMutableArray *> *ref, NSInteger sub ) :
428  OOArraySub<OOClassPtr<CNAME> >( ref, sub ) {
429  }
430 
431  oo_inline virtual id set ( id val ) const OO_RETURNS {
432  OOClassPtr<CNAME> tmp( this->get( NO ), val );
433  return OOArraySub<OOClassPtr<CNAME> >::set( val );
434  }
435 
436 public:
437  oo_inline OOArcArraySub &operator = ( CNAME *ptr ) {
438  this->set( OOClassPtr<CNAME>( ptr ) );
439  return *this;
440  }
441  oo_inline OOArcArraySub<CNAME> operator [] ( int sub ) const {
442  return OOArcArraySub<CNAME>( (OOArraySub<NSMutableArray *> *)this, sub );
443  }
444  oo_inline OOArcDictSub<CNAME> operator [] ( id sub ) const {
445  return OOArcDictSub<CNAME>( (OOArraySub<NSMutableDictionary *> *)this, sub );
446  }
447  oo_inline OOArcDictSub<CNAME> operator [] ( CFStringRef sub ) const {
448  return (*this)[OO_BRIDGE(id)sub];
449  }
450  oo_inline OOArcDictSub<CNAME> operator [] ( const char *sub ) const {
451  return (*this)[(id)*OOString( sub )];
452  }
453  oo_inline OOClassPtr<CNAME> operator ~ () {
454  OOClassPtr<CNAME> save( this->get( NO ), nil );
455  return OOArraySub<OOClassPtr<CNAME> >::operator ~();
456  }
457 };
458 
459 template <typename CNAME>
460 class OOClassDict;
461 
462 template <typename CNAME>
463 class OOArcDictSub : public OODictionarySub<OOClassPtr<CNAME> > {
464  friend class OOClassDict<CNAME>;
465  friend class OOArcArraySub<CNAME>;
466 
467  oo_inline OOArcDictSub( const OOClassDict<CNAME> *root, id key ) :
468  OODictionarySub<OOClassPtr<CNAME> >( root, key ) {
469  }
470  oo_inline OOArcDictSub( OOArraySub<NSMutableDictionary *> *ref, id sub ) :
471  OODictionarySub<OOClassPtr<CNAME> >( ref, sub ) {
472  }
473  oo_inline OOArcDictSub( OODictionarySub<NSMutableDictionary *> *ref, id sub ) :
474  OODictionarySub<OOClassPtr<CNAME> >( ref, sub ) {
475  }
476 
477  oo_inline virtual id set( id val ) const OO_RETURNS {
478  OOClassPtr<CNAME> tmp( this->get( NO ), val );
479  return OODictionarySub<OOClassPtr<CNAME> >::set( val );
480  }
481 
482 public:
483  oo_inline OOArcDictSub &operator = ( CNAME *ptr ) {
484  this->set( OOClassPtr<CNAME>( ptr ) );
485  return *this;
486  }
487  oo_inline OOArcArraySub<CNAME> operator [] ( int sub ) const {
488  return OOArcArraySub<CNAME>( (OODictionarySub<NSMutableArray *> *)this, sub );
489  }
490  oo_inline OOArcDictSub<CNAME> operator [] ( id sub ) const {
491  return OOArcDictSub<CNAME>( (OODictionarySub<NSMutableDictionary *> *)this, sub );
492  }
493  oo_inline OOArcDictSub<CNAME> operator [] ( CFStringRef sub ) const {
494  return (*this)[OO_BRIDGE(id)sub];
495  }
496  oo_inline OOArcDictSub<CNAME> operator [] ( const char *sub ) const {
497  return (*this)[*OOString( sub )];
498  }
499  oo_inline OOClassPtr<CNAME> operator ~ () {
500  OOClassPtr<CNAME> save( this->get( NO ), nil );
501  return OODictionarySub<OOClassPtr<CNAME> >::operator ~();
502  }
503 };
504 
505 /*===============================================================================*/
506 /*============================== Class containers ===============================*/
507 
508 /**
509  A wrapper for an array of heap allocated C++ class pointers stored as NSValue objects.
510 
511  Usage:
512  <pre>
513  \@interface ExampleClass {
514  OOClassArray<aclass> CPPinstances;
515  }
516 
517  \@implementation
518 
519  - function {
520  for ( int i=0 ; i<100 ; i+=10 )
521  CPPinstances[i] = new aclass();
522  ~CPPinstances; /// instances are deleted
523  }
524 
525  \@end
526 
527  - function {
528  OOClassArray<aclass> x;
529  x[99] = new aclass();
530  } // instance deleteed
531 
532  </pre>
533  */
534 
535 template <typename CNAME>
536 class OOClassArray : public OOArray<OOClassPtr<CNAME> > {
537 #ifndef OO_ARC
538  // delete each element to call its destructor
539  oo_inline NSMutableArray *set( NSMutableArray *val ) OO_RETURNS {
540  NSMutableArray *old = !*this ? nil : this->get();
541  if ( old && val != old && [old retainCount] == 1 ) /////
542  clear();
543  return OOArray<OOClassPtr<CNAME> >::set( val );
544  }
545  oo_inline void destruct() { this->set( OONil ); }
546 #endif
547 public:
548  oo_inline OOClassArray() {}
549  oo_inline OOClassArray( NSMutableArray *val ) { this->set( val ); }
550  oo_inline OOClassArray( const OOClassArray &val ) { this->set( val.get() ); }
551  oo_inline ~OOClassArray() { this->destruct(); }
552 
553  oo_inline OOArcArraySub<CNAME> operator[] ( NSInteger idx ) {
554  return OOArcArraySub<CNAME>( this, idx );
555  }
556  oo_inline OOArcArraySub<CNAME> operator [] ( long sub ) const {
557  return OOArcArraySub<CNAME>( this, sub );
558  }
559 
560  oo_inline OOClassArray &operator = ( NSMutableArray *val ) { this->set( val ); return *this; };
561  oo_inline OOClassArray &operator = ( OOClassArray *val ) { this->set( val.get() ); return *this; };
562 
563  oo_inline void clear() {
564  while ( [this->get() count] )
565  ~(*this)[-1];
566  }
567  oo_inline OOClassArray<CNAME> operator ~ () {
568  OOClassArray<CNAME> save = this->get();
569  this->destruct();
570  return save;
571  }
572 };
573 
574 /**
575  NSMutable dictionary wrapper for storing heap allocated C++ instances by key.
576 
577  Usage:
578  <pre>
579  OOClassDict<aclass> a
580  a[@"KEY"] = new aclass[];
581  ~a[@"KEY"] // instance deleted
582  </pre>
583  */
584 
585 template <typename CNAME>
586 class OOClassDict : public OODictionary<OOClassPtr<CNAME> > {
587 protected:
588 #ifndef OO_ARC
589  // delete each entry to call its destructor
590  oo_inline NSMutableDictionary *set( NSMutableDictionary *val ) OO_RETURNS {
591  NSMutableDictionary *old = !*this ? nil : this->get();
592  if ( old && val != old && [old retainCount] == 1 )
593  clear();
594  return OODictionary<OOClassPtr<CNAME> >::set( val );
595  }
596  oo_inline void destruct() { this->set( OONil ); }
597 #endif
598 public:
599  oo_inline OOClassDict() {}
600  oo_inline OOClassDict( NSMutableDictionary *val ) { this->set( val ); }
601  oo_inline OOClassDict( const OOClassDict &val ) { this->set( val.get() ); }
602  oo_inline ~OOClassDict() { this->destruct(); }
603 
604  oo_inline OOClassDict &operator = ( NSMutableArray *val ) { this->set( val ); return *this; };
605  oo_inline OOClassDict &operator = ( const OOClassDict &val ) { this->set( val.get() ); return *this; };
606 
607  oo_inline OOArcDictSub<CNAME> operator[] ( id key ) const {
608  return OOArcDictSub<CNAME>( this, key );
609  }
610  oo_inline OOArcDictSub<CNAME> operator [] ( const char *sub ) const {
611  return (*this)[OOString(sub)];
612  }
613  oo_inline OOArcDictSub<CNAME> operator [] ( cOOString sub ) const {
614  return (*this)[*sub];
615  }
616  oo_inline OOArcDictSub<CNAME> operator [] ( const CFStringRef sub ) const {
617  return (*this)[OO_BRIDGE(id)sub];
618  }
619 
620  oo_inline void clear() {
621  OOArray<id> keys = [this->get() allKeys];
622 #if 00000
623  for ( id key in [old allKeys] )
624  ~(*this)[key];
625 #else
626  for ( int i=0 ; i<keys ; i++ )
627  ~(*this)[*keys[i]];
628 #endif
629  }
630  oo_inline OOClassDict<CNAME> operator ~ () {
631  OOClassDict<CNAME> save = this->get();
632  this->destruct();
633  return save;
634  }
635 };
636 
637 template <typename CNAME>
638 inline void OOClassPtr<CNAME>::replace( id next ) {
639  BOOL isClassValue = [*this isKindOfClass:[NSValue class]];
640 #ifdef OO_ARC
641  if ( next && [next isKindOfClass:[NSValue class]] )
642  ((OOClassCtr<CNAME> *)[next pointerValue])->ctr++;
643  BOOL shouldDelete = isClassValue ? this->pget()->ctr-- == 1 : !!*this;
644 #else
645  BOOL shouldDelete = [*this retainCount] == 1;
646 #endif
647 
648  if ( !shouldDelete )
649  return;
650  if ( isClassValue ) {
651  OOTrace( @"0x%08lx %s", (OOAddress)this, "CDESTROY" );
652  delete this->pget();
653  this->destruct();
654  }
655  else if ( [*this isKindOfClass:[NSArray class]] )
656  OOClassArray<CNAME>( (id)this->get() ).clear();
657  else if ( [*this isKindOfClass:[NSDictionary class]] )
658  OOClassDict<CNAME>( (id)this->get() ).clear();
659  else
660  OOWarn( @"Invalid class released %@", NSStringFromClass( [this->get() class] ) );
661 }
662 
663 /**
664  Simple refrence counting for C/C++ objects
665  */
666 template <typename CNAME>
667 class OOCounted;
668 
669 template <typename CNAME>
670 class OOCounter {
671  friend class OOCounted<CNAME>;
672  CNAME *ptr;
673  unsigned references;
674  oo_inline OOCounter( CNAME *ptr ) {
675  this->ptr = ptr;
676  this->references = 1;
677  }
678  oo_inline OOCounter *retain() {
679  references++;
680  return this;
681  }
682  oo_inline void release() {
683  if ( --references == 0 ) {
684  delete ptr;
685  delete this;
686  }
687  }
688 };
689 
690 template <typename CNAME>
691 class OOCounted {
692  OOCounter<CNAME> *counter;
693 public:
694  oo_inline OOCounted() {
695  counter = NULL;
696  }
697  oo_inline OOCounted( CNAME *ptr ) {
698  counter = new OOCounter<CNAME>( ptr );
699  }
700  oo_inline OOCounted( const OOCounted &counted ) {
701  counter = counted.counter->retain();
702  }
703  oo_inline OOCounted &operator = ( const OOCounted &counted ) {
704  OOCounter<CNAME> *old = counter;
705  counter = counted.counter->retain();
706  if ( old )
707  old->release();
708  return *this;
709  }
710  oo_inline CNAME *operator -> () {
711  return counter->ptr;
712  }
713  oo_inline CNAME &operator * () {
714  return *counter->ptr;
715  }
716  oo_inline ~OOCounted() {
717  if ( counter )
718  counter->release();
719  }
720 };
721 
722 #endif
723 #endif