/*=============================================================================
	CACFArray.h

	$Log: CACFArray.h,v $
	Revision 1.11  2004/11/24 20:20:48  jcm10
	add methods for insertion
	
	Revision 1.10  2004/09/14 19:53:58  jcm10
	add GetBool()
	
	Revision 1.9  2004/08/01 01:13:08  bills
	add AsPropertyList
	
	Revision 1.8  2004/02/27 01:43:35  jcm10
	add RemoveItem(), Sort(), SortNumbers(), and SortStrings()
	
	Revision 1.7  2004/01/29 00:24:18  jcm10
	add CanModify() and Clear()
	
	Revision 1.6  2004/01/12 20:35:52  jcm10
	add some new methods
	
	Revision 1.5  2003/11/20 22:56:53  dwyatt
	__COREAUDIO_USE_FLAT_INCLUDES__
	
	Revision 1.4  2003/10/13 23:47:06  ealdrich
	Add include of CoreFoundation.h (needed for CFArrayRef and CFDictionaryRef definitions)
	
	Revision 1.3  2003/05/27 21:18:46  jcm10
	add GetTypeID
	
	Revision 1.2  2003/05/22 19:07:18  jcm10
	rework this class to prevent polymorphic problems with CFTypes
	
	Revision 1.1  2003/05/04 00:00:16  jcm10
	first checked in
	
	Revision 0.0  Sat May 03 2003 11:29:31 US/Pacific  moorf
	Created
		
	$NoKeywords: $
=============================================================================*/
#if !defined(__CACFArray_h__)
#define __CACFArray_h__

//=============================================================================
//	Includes
//=============================================================================

//	System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
	#include <CoreAudio/CoreAudioTypes.h>
	#include <CoreFoundation/CoreFoundation.h>
#else
	#include <CoreAudioTypes.h>
	#include <CoreFoundation.h>
#endif

//=============================================================================
//	CACFArray
//=============================================================================

class CACFArray
{

//	Construction/Destruction
public:
						CACFArray(bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
						CACFArray(UInt32 inMaxNumberItems, bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, inMaxNumberItems, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
						CACFArray(CFArrayRef inCFArray, bool inRelease) : mCFArray(const_cast<CFMutableArrayRef>(inCFArray)), mRelease(inRelease), mMutable(false) {}
						CACFArray(CFMutableArrayRef inCFArray, bool inRelease) : mCFArray(inCFArray), mRelease(inRelease), mMutable(true) {}
						CACFArray(const CACFArray& inArray) : mCFArray(inArray.mCFArray), mRelease(inArray.mRelease), mMutable(inArray.mMutable) { if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } }
	CACFArray&			operator=(const CACFArray& inArray) { mCFArray = inArray.mCFArray; mRelease = inArray.mRelease; mMutable = inArray.mMutable; if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } return *this; }
						~CACFArray() { if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } }

//	Attributes
public:
	bool				IsValid() const { return mCFArray != NULL; }
	bool				IsMutable() const { return IsMutable(); }
	bool				CanModify() const { return mMutable && (mCFArray != NULL); }
	
	bool				WillRelease() const { return mRelease; }
	void				ShouldRelease(bool inRelease) { mRelease = inRelease; }
	
	CFTypeID			GetTypeID() const { return CFGetTypeID(mCFArray); }
	
	CFArrayRef			GetCFArray() const { return mCFArray; }
	CFArrayRef			CopyCFArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
	
	CFMutableArrayRef	GetCFMutableArray() const { return mCFArray; }
	CFMutableArrayRef	CopyCFMutableArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
	CFPropertyListRef   AsPropertyList() const { return mCFArray; }

	void				SetCFMutableArrayFromCopy(CFArrayRef inArray, bool inRelease = true) { if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } mMutable = true; mRelease = inRelease; mCFArray = CFArrayCreateMutableCopy(NULL, 0, inArray); }

//	Item Operations
public:
	UInt32				GetNumberItems() const { UInt32 theAnswer = 0; if(mCFArray != NULL) { theAnswer = CFArrayGetCount(mCFArray); } return theAnswer; }
	bool				HasItem(const void* inItem) const;
	void				RemoveItem(const void* inItem) { UInt32 theIndex; if(CanModify() && GetIndexOfItem(inItem, theIndex)) { RemoveItemAtIndex(theIndex); } }
	bool				GetIndexOfItem(const void* inItem, UInt32& outIndex) const;
	void				RemoveItemAtIndex(UInt32 inIndex) { if(CanModify()) { CFArrayRemoveValueAtIndex(mCFArray, inIndex); } }
	void				Clear() { if(CanModify()) { CFArrayRemoveAllValues(mCFArray); } }
	void				Sort(CFComparatorFunction inCompareFunction) { if(CanModify()) { CFRange theRange = { 0, CFArrayGetCount(mCFArray) }; CFArraySortValues(mCFArray, theRange, inCompareFunction, NULL); } }
	void				SortNumbers() { Sort((CFComparatorFunction)CFNumberCompare); }
	void				SortStrings() { Sort((CFComparatorFunction)CFStringCompare); }
	
	bool				GetBool(UInt32 inIndex, bool& outValue) const;
	bool				GetSInt32(UInt32 inIndex, SInt32& outItem) const;
	bool				GetUInt32(UInt32 inIndex, UInt32& outItem) const;
	bool				GetSInt64(UInt32 inIndex, SInt64& outItem) const;
	bool				GetUInt64(UInt32 inIndex, UInt64& outItem) const;
	bool				GetFloat32(UInt32 inIndex, Float32& outItem) const;
	bool				GetFloat64(UInt32 inIndex, Float64& outItem) const;
	bool				GetString(UInt32 inIndex, CFStringRef& outItem) const;
	bool				GetArray(UInt32 inIndex, CFArrayRef& outItem) const;
	bool				GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const;
	bool				GetCFType(UInt32 inIndex, CFTypeRef& outItem) const;
	
	bool				AppendSInt32(SInt32 inItem);
	bool				AppendUInt32(UInt32 inItem);
	bool				AppendSInt64(SInt64 inItem);
	bool				AppendUInt64(UInt64 inItem);
	bool				AppendFloat32(Float32 inItem);
	bool				AppendFloat64(Float64 inItem);
	bool				AppendString(const CFStringRef inItem);
	bool				AppendArray(const CFArrayRef inItem);
	bool				AppendDictionary(const CFDictionaryRef inItem);
	bool				AppendCFType(const CFTypeRef inItem);
	
	bool				InsertSInt32(UInt32 inIndex, SInt32 inItem);
	bool				InsertUInt32(UInt32 inIndex, UInt32 inItem);
	bool				InsertSInt64(UInt32 inIndex, SInt64 inItem);
	bool				InsertUInt64(UInt32 inIndex, UInt64 inItem);
	bool				InsertFloat32(UInt32 inIndex, Float32 inItem);
	bool				InsertFloat64(UInt32 inIndex, Float64 inItem);
	bool				InsertString(UInt32 inIndex, const CFStringRef inItem);
	bool				InsertArray(UInt32 inIndex, const CFArrayRef inItem);
	bool				InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
	bool				InsertCFType(UInt32 inIndex, const CFTypeRef inItem);
	
	bool				SetSInt32(UInt32 inIndex, SInt32 inItem);
	bool				SetUInt32(UInt32 inIndex, UInt32 inItem);
	bool				SetSInt64(UInt32 inIndex, SInt64 inItem);
	bool				SetUInt64(UInt32 inIndex, UInt64 inItem);
	bool				SetFloat32(UInt32 inIndex, Float32 inItem);
	bool				SetFloat64(UInt32 inIndex, Float64 inItem);
	bool				SetString(UInt32 inIndex, const CFStringRef inItem);
	bool				SetArray(UInt32 inIndex, const CFArrayRef inItem);
	bool				SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
	bool				SetCFType(UInt32 inIndex, const CFTypeRef inItem);

//	Implementation
private:
	CFMutableArrayRef	mCFArray;
	bool				mRelease;
	bool				mMutable;
	
};

#endif
