/*=============================================================================
	CACFString.h

	$Log: CACFString.h,v $
	Revision 1.15  2004/10/06 19:50:15  jcm10
	add accessors for getting the length of a CFString in both characters and bytes
	
	Revision 1.14  2004/08/05 01:26:46  jcm10
	add an encoding argument to the various GetCString methods
	
	Revision 1.13  2004/07/19 19:07:45  jcm10
	add a static method to CACFString for getting a C string or Unicode string from a CFStringRef
	
	Revision 1.12  2004/04/13 07:06:52  jcm10
	fix compiler warnings
	
	Revision 1.11  2004/01/12 20:36:40  jcm10
	IsValid() needs to be const
	
	Revision 1.10  2003/12/08 20:58:27  jcm10
	add a new constructor and an Append() method to CACFMutableString
	
	Revision 1.9  2003/11/20 22:56:53  dwyatt
	__COREAUDIO_USE_FLAT_INCLUDES__
	
	Revision 1.8  2003/05/22 19:06:31  jcm10
	add constructors for building CFStrings out of C strings
	
	Revision 1.7  2002/08/07 23:14:47  jcm10
	add GetUnicodeString
	
	Revision 1.6  2002/07/07 00:46:31  jcm10
	add default a default constructor
	
	Revision 1.5  2002/06/05 22:38:25  jcm10
	overhaul how default device management works
	
	Revision 1.4  2002/04/18 02:20:12  jcm10
	clean up the header inclusion
	
	Revision 1.3  2002/04/10 02:40:52  jcm10
	synch the MP-4 code
	
	Revision 1.2  2002/04/10 01:15:20  jcm10
	assignment operators return a reference
	
	Revision 1.1  2002/03/01 01:52:40  jcm10
	moved here from ../Utility
	
	Revision 1.3  2001/04/05 01:32:26  jcm10
	add CACFMutableString
	
	Revision 1.2  2001/03/20 00:03:25  jcm10
	make the default devices persistent
	
	Revision 1.1  2001/03/14 23:48:38  jcm10
	Lots of changes to support the new driver API
	
	Revision 0.0  2001/02/23 14:03:24  jcm10
	created
		
	$NoKeywords: $
=============================================================================*/
#if !defined(__CACFString_h__)
#define __CACFString_h__

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

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

//=============================================================================
//	CACFString
//=============================================================================

class	CACFString
{
//	Construction/Destruction
public:
					CACFString() : mCFString(NULL), mWillRelease(true) {}
					CACFString(CFStringRef inCFString, bool inWillRelease = true) : mCFString(inCFString), mWillRelease(inWillRelease) {}
					CACFString(const char* inCString, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(inWillRelease) {}
					CACFString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, inCStringEncoding)), mWillRelease(inWillRelease) {}
					~CACFString() { Release(); }
					CACFString(const CACFString& inString) : mCFString(inString.mCFString), mWillRelease(inString.mWillRelease) { Retain(); }
	CACFString&		operator=(const CACFString& inString) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); return *this; }
	CACFString&		operator=(CFStringRef inCFString) { Release(); mCFString = inCFString; mWillRelease = true; return *this; }

private:
	void			Retain() { if(mWillRelease && (mCFString != NULL)) { CFRetain(mCFString); } }
	void			Release() { if(mWillRelease && (mCFString != NULL)) { CFRelease(mCFString); } }
	
	CFStringRef		mCFString;
	bool			mWillRelease;

//	Operations
public:
	void			AllowRelease() { mWillRelease = true; }
	void			DontAllowRelease() { mWillRelease = false; }
	bool			IsValid() const { return mCFString != NULL; }

//	Value Access
public:
	CFStringRef		GetCFString() const { return mCFString; }
	CFStringRef		CopyCFString() const { if(mCFString != NULL) { CFRetain(mCFString); } return mCFString; }
	UInt32			GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = CFStringGetLength(mCFString); } return theAnswer; }
	UInt32			GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = GetStringByteLength(mCFString, inEncoding); } return theAnswer; }
	void			GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { GetCString(mCFString, outString, ioStringSize, inEncoding); }
	void			GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { GetUnicodeString(mCFString, outString, ioStringSize); }

	static UInt32	GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
	static void		GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
	static void		GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize);
	
};

inline bool	operator<(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareLessThan; }
inline bool	operator==(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareEqualTo; }
inline bool	operator!=(const CACFString& x, const CACFString& y) { return !(x == y); }
inline bool	operator<=(const CACFString& x, const CACFString& y) { return (x < y) || (x == y); }
inline bool	operator>=(const CACFString& x, const CACFString& y) { return !(x < y); }
inline bool	operator>(const CACFString& x, const CACFString& y) { return !((x < y) || (x == y)); }

//=============================================================================
//	CACFMutableString
//=============================================================================

class	CACFMutableString
{
//	Construction/Destruction
public:
						CACFMutableString() : mCFMutableString(NULL), mWillRelease(true) {}
						CACFMutableString(CFMutableStringRef inCFMutableString, bool inWillRelease = true) : mCFMutableString(inCFMutableString), mWillRelease(inWillRelease) {}
						CACFMutableString(CFStringRef inStringToCopy, bool /*inMakeCopy*/, bool inWillRelease = true) : mCFMutableString(CFStringCreateMutableCopy(NULL, 0, inStringToCopy)), mWillRelease(inWillRelease) {}
						CACFMutableString(const char* inCString, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
						CACFMutableString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString, inCStringEncoding); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
						~CACFMutableString() { Release(); }
						CACFMutableString(const CACFMutableString& inString) : mCFMutableString(inString.mCFMutableString), mWillRelease(inString.mWillRelease) { Retain(); }
	CACFMutableString	operator=(const CACFMutableString& inString) { Release(); mCFMutableString = inString.mCFMutableString; mWillRelease = inString.mWillRelease; Retain(); return *this; }
	CACFMutableString	operator=(CFMutableStringRef inCFMutableString) { Release(); mCFMutableString = inCFMutableString; mWillRelease = true; return *this; }

private:
	void				Retain() { if(mWillRelease && (mCFMutableString != NULL)) { CFRetain(mCFMutableString); } }
	void				Release() { if(mWillRelease && (mCFMutableString != NULL)) { CFRelease(mCFMutableString); } }
	
	CFMutableStringRef	mCFMutableString;
	bool				mWillRelease;

//	Operations
public:
	void				AllowRelease() { mWillRelease = true; }
	void				DontAllowRelease() { mWillRelease = false; }
	bool				IsValid() { return mCFMutableString != NULL; }
	void				Append(CFStringRef inString) { CFStringAppend(mCFMutableString, inString); }

//	Value Access
public:
	CFMutableStringRef	GetCFMutableString() const { return mCFMutableString; }
	CFMutableStringRef	CopyCFMutableString() const { if(mCFMutableString != NULL) { CFRetain(mCFMutableString); } return mCFMutableString; }
	UInt32				GetLength() const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CFStringGetLength(mCFMutableString); } return theAnswer; }
	UInt32				GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CACFString::GetStringByteLength(mCFMutableString, inEncoding); } return theAnswer; }
	void				GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { CACFString::GetCString(mCFMutableString, outString, ioStringSize, inEncoding); }
	void				GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { CACFString::GetUnicodeString(mCFMutableString, outString, ioStringSize); }

};

#endif
