⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mac_pref_cf.cpp

📁 linux下的一款播放器
💻 CPP
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: mac_pref_cf.cpp,v 1.8.8.3 2004/07/09 01:47:27 hubbe Exp $ *  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. *  * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks.  You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL.  Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. *  * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. *  * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. *  * Technology Compatibility Kit Test Suite(s) Location: *    http://www.helixcommunity.org/content/tck *  * Contributor(s): *  * ***** END LICENSE BLOCK ***** */#include "platform/mac/mac_pref_cf.h"#include "hxbuffer.h"#include "filespecutils.h"const char * kPrefPrefixSeparator = "\\"; // backslash since no Windows programmer will use it inside of a key// 	call open_pref() to automatically create the correct Macintosh specific preference object.CMacPref * CMacPref::open_pref(const char* pCompanyName, const char* pProductName, int nProdMajorVer, int nProdMinorVer, BOOL bCommon){    return new CMacPref(pCompanyName, pProductName, nProdMajorVer, nProdMinorVer, bCommon);}// 	Constructor NOTE: use open_pref() to create an instance of this classCMacPref::CMacPref(const char* pCompanyName, const char* pProductName, int nProdMajorVer, int nProdMinorVer, BOOL bCommon){  	CHXString strBundleID;	CFStringRef userNameRef, hostNameRef;	CHXCFString cfsPrefsBundleName;		check(pCompanyName && *pCompanyName);	check(pProductName && *pProductName);		check(strcspn(pCompanyName, " .,;:/\\!@#$%^&*()\"") == strlen(pCompanyName)); // ensure there are no punctuation		// prefs common among all users are "any user, current host"	// prefs for just the current user are "current user, any host"		userNameRef = bCommon ? kCFPreferencesAnyUser : kCFPreferencesCurrentUser;	hostNameRef = bCommon ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;		m_pPrefFile = NULL;	m_strProductNamePrefix = pProductName;	// Added support for overloading the preference file name.	// If the HelixPreferenceFileID preferences exists in the main bundle's pref's, then use its value as the pref. filename.	CFBundleRef mainBundleRef = NULL;        CFStringRef mainBundleID = NULL;        CFStringRef helixPrefFileID = NULL;                mainBundleRef = CFBundleGetMainBundle();                if (mainBundleRef)        {            // if previous step succeeded (failure possible with CFM app)            mainBundleID = CFBundleGetIdentifier( mainBundleRef );        }                if (mainBundleID)        {            // if previous step succeeded            helixPrefFileID = ( CFStringRef ) CFPreferencesCopyAppValue( CFSTR( "HelixPreferenceFileID" ), mainBundleID );        }        	if ( helixPrefFileID )	{		// Support mapping of helix product names to application specific values.		m_pPrefFile = CMacPrefFile::CreatePrefSystemObject( helixPrefFileID, userNameRef, hostNameRef );		CFDataRef helixPrefMapRef = ( CFDataRef ) CFPreferencesCopyAppValue( CFSTR( "HelixPrefMap" ), helixPrefFileID );		if ( helixPrefMapRef )		{			CFStringRef errorString;			CFDictionaryRef helixPrefMap = ( CFDictionaryRef ) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, helixPrefMapRef, kCFPropertyListImmutable, &errorString );			if ( helixPrefMap )			{				CFStringRef key = CFStringCreateWithCString( kCFAllocatorDefault, m_strProductNamePrefix, kCFStringEncodingUTF8 );				if ( key )				{					CFStringRef mappedPrefixName = ( CFStringRef ) CFDictionaryGetValue( helixPrefMap, key );					if ( mappedPrefixName )					{						m_strProductNamePrefix = mappedPrefixName;					}					CFRelease( key );				}				CFRelease( helixPrefMap );			}			if ( errorString )			{				CFRelease( errorString );			}			CFRelease( helixPrefMapRef );		}		CFRelease( helixPrefFileID );	}	else	{		strBundleID.Format("com.%s.%s", pCompanyName, pProductName);		cfsPrefsBundleName = strBundleID;		m_pPrefFile = CMacPrefFile::CreatePrefSystemObject( cfsPrefsBundleName, userNameRef, hostNameRef );	}	// save the product name which becomes the prefix for each pref entry, like "RealMediaSDK\"	m_strProductNamePrefix += kPrefPrefixSeparator;		check_nonnull(m_pPrefFile);		if (bCommon)	{		HX_ASSERT(!"Using machine-wide prefs, which fails for non-admin users. Absolutely sure?");	}}// 	class destructor 	CMacPref::~CMacPref (void){	commit_prefs();		// writes prefs to disk		EndAllSubPrefs();	// frees up the stack of CHXStrings		if (m_pPrefFile)	{		HX_DELETE(m_pPrefFile);	}}HX_RESULT CMacPref::commit_prefs(void){	require_nonnull_return(m_pPrefFile, HXR_NOT_INITIALIZED);		m_pPrefFile->Synchronize();	// Boolean bSuccess = CFPreferencesAppSynchronize(m_cfsPrefsBundleName);		//return bSuccess ? HXR_OK : HXR_FAIL;		return HXR_OK;}void CMacPref::MakePrefKeyCF(const char *pPrefKey, CHXCFString& outCfsRealKey){	CHXString strKey;		MakePrefKey(pPrefKey, strKey);		outCfsRealKey = strKey;	}void CMacPref::MakePrefKey(const char *pPrefKey, CHXString& outMadeKey){	CHXString strInKey;		//check(strstr(pPrefKey, kPrefPrefixSeparator) == 0); // check that the separator isn't in a key	// alas, the Core sometimes builds subprefs by lazily including backslashes		strInKey = pPrefKey;		// delete any leading separator at the beginning of the string	if (strInKey.Find(kPrefPrefixSeparator) == 0)	{		strInKey = strInKey.Right(strInKey.GetLength() - strlen(kPrefPrefixSeparator));	}		// the full key is constructed as "Product/Subpref/Key"		outMadeKey = m_strProductNamePrefix;		if (m_strSubPrefPrefix.IsEmpty())	{		// no subpref prefix		outMadeKey += strInKey;	}	else	{		// prepend with subpref prefix		outMadeKey += m_strSubPrefPrefix;		outMadeKey += strInKey;	}}HX_RESULT CMacPref::MakeIHXBuffer(const char *pData, IHXBuffer*& pBuffer){	check_nonnull(pData);		return CHXBuffer::FromCharArray(pData, &pBuffer);}//  read_pref reads the preference specified by Key to the Buffer.HX_RESULT CMacPref::read_pref(const char* pPrefKey, IHXBuffer*& pBuffer){	require_nonnull_return(m_pPrefFile, HXR_NOT_INITIALIZED);	CHXCFString cfsKey;	CHXCFString cfsPref;		MakePrefKeyCF(pPrefKey, cfsKey);		cfsPref = (CFStringRef) m_pPrefFile->CopyValue(cfsKey);	if (cfsPref.IsSet())	{		CHXString str;				str = cfsPref;				return MakeIHXBuffer((const char *) str, pBuffer);	}		return HXR_FAIL;} //  write_pref writes (saves) the preference specified by pPrefKey from the Buffer. HX_RESULT CMacPref::write_pref(const char* pPrefKey, IHXBuffer* pBuffer){   	require_nonnull_return(m_pPrefFile, HXR_NOT_INITIALIZED);		CHXCFString cfsKey;	CHXCFString cfsValue((const char *) pBuffer->GetBuffer());	MakePrefKeyCF(pPrefKey, cfsKey);	// CFPreferences doesn't return an error for this...	m_pPrefFile->SetValue(cfsKey, cfsValue);	//::CFPreferencesSetValue(cfsKey, cfsValue, m_cfsPrefsBundleName, m_UserNameRef, m_HostNameRef);		return HXR_OK;}//  delete_pref deletes the preference specified by Key from the Buffer.HX_RESULT CMacPref::delete_pref(const char* pPrefKey){       return remove_pref(pPrefKey);}HX_RESULT CMacPref::remove_pref(const char* pPrefKey){	// pPrefKey is either a key (in the current subpref) or a subpref branch name	// (also in the current subpref)		// try deleting that key directly	RemoveSinglePrefInternal(pPrefKey);		// now try deleting that key as a subpref subtree: we'll set to the subpref and	// remove all keys inside of it	if (pPrefKey && *pPrefKey)	{		const UINT32 kFirstKeyIndex = 0;		CHXString strKey;		const BOOL kReturnDeeperNestings = TRUE;				BeginSubPref(pPrefKey);		while (1)		{			HX_RESULT res = GetPrefKeyInternal(kFirstKeyIndex, kReturnDeeperNestings, strKey); // we want "sub/x" and "sub/x/y"			if (FAILED(res)) break;						RemoveSinglePrefInternal(strKey);		}		EndSubPref();	}		return HXR_OK;}void CMacPref::RemoveSinglePrefInternal(const char* pPrefKey){	require_nonnull_void_return(m_pPrefFile);	const CFPropertyListRef kRemovePreference = NULL;		CHXCFString cfsKey;		MakePrefKeyCF(pPrefKey, cfsKey);	m_pPrefFile->SetValue(cfsKey, kRemovePreference); // CFPrefs doesn't return an error for this}HX_RESULT CMacPref::remove_indexed_pref(const char* pPrefKey){	CHXString strKey;	UINT16 index;	IHXBuffer* pBuffer;	HX_RESULT err;		index = 1;	while (1)	{		strKey.Format("%s%d", pPrefKey, index);				// if there's one with this index, remove it		pBuffer = nil;				err = read_pref(strKey, pBuffer);		HX_RELEASE(pBuffer);		if (SUCCEEDED(err))		{			err = remove_pref(strKey);			check_success(err);						index++;		}		else		{				// no more keyN prefs here; we're done			break;		}	}	return HXR_OK;}HX_RESULT CMacPref::BeginSubPref(const char* szSubPref){	check(szSubPref && strlen(szSubPref));		// if there was already a prefix, push it onto the stack to save it for later	if (!m_strSubPrefPrefix.IsEmpty())	{		CHXString *pStrNew = new CHXString;		check_nonnull(pStrNew);				*pStrNew = (const char *) m_strSubPrefPrefix;				m_arrSubKeyStack.Add(&pStrNew);	}		// now add the new subpref prefix part and a separator to the previous subpref prefix	m_strSubPrefPrefix += szSubPref;	m_strSubPrefPrefix += kPrefPrefixSeparator;	return HXR_OK;}HX_RESULT CMacPref::EndSubPref(){	require_return(!m_strSubPrefPrefix.IsEmpty(), HXR_FAIL);		m_strSubPrefPrefix.Empty();	if (!m_arrSubKeyStack.IsEmpty())	{		// we're nested in; pop an old prefix off the stack		CHXString *pStrOld;		HX_RESULT res = HXR_OK;				pStrOld = (CHXString*)m_arrSubKeyStack.GetAt(m_arrSubKeyStack.GetSize()-1);		m_arrSubKeyStack.RemoveAt(m_arrSubKeyStack.GetSize()-1);		check_success(res);				if (SUCCEEDED(res))		{			m_strSubPrefPrefix = (const char *) *pStrOld;			delete pStrOld;		}	}	return HXR_OK;}void CMacPref::EndAllSubPrefs(){	while (!m_arrSubKeyStack.IsEmpty())	{		// get rid of those old CHxStrings		EndSubPref();	}	m_strSubPrefPrefix.Empty();}		HX_RESULT CMacPref::GetPrefKey(UINT32 nIndex,IHXBuffer*& pBuffer){	const BOOL kDontReturnDeeperNestings = FALSE;		CHXString strKey;		HX_RESULT res = GetPrefKeyInternal(nIndex, kDontReturnDeeperNestings, strKey);	if ( SUCCEEDED( res ) )	{		res = MakeIHXBuffer((const char *) strKey, pBuffer);	}	return res;}HX_RESULT CMacPref::GetPrefKeyInternal(UINT32 nIndex, BOOL bReturnDeeperNestings, CHXString& outStrKey){	require_nonnull_return(m_pPrefFile, HXR_NOT_INITIALIZED);	CFArrayRef cfArray;	HX_RESULT res;		res = HXR_FAIL;		// Get the array of keys from our preferences file, step through the keys, and look for	// any beginning with the current SubPref prefix.	//	// We only want to count and return keys with the matching SubPref prefix that are not 	// nested more deeply.  For example, for the SubPref  'foo', we want to return 'foo\a' 	// and 'foo\b' but not 'foo\x\c'		cfArray = m_pPrefFile->CopyKeyList();	//cfArray = CFPreferencesCopyKeyList(m_cfsPrefsBundleName, m_UserNameRef, m_HostNameRef);	if (cfArray)	{		CFIndex numArrayElements, nCountDown, idx;		CHXString strCurrKey, strCurrKeyAfterPrefix, strActivePrefix;				// make the current prefix including product name and any subpref		MakePrefKey("", strActivePrefix);				nCountDown = nIndex; // when nCountDown hits zero, we return the next appropriate key				numArrayElements = CFArrayGetCount(cfArray);				for (idx = 0; idx < numArrayElements; idx++)		{			CFStringRef cfsRef; // we're not using CHXCFString since we won't release these; they belong to the array						cfsRef = (CFStringRef) CFArrayGetValueAtIndex(cfArray, idx);			check_nonnull(cfsRef);						if (cfsRef)			{				UINT32 prefixLen, keyLen;								// convert this key to a CHXString				strCurrKey = cfsRef;								// if the left side of the key matches our current prefix,				// then this counts								prefixLen = strActivePrefix.GetLength();				keyLen = strCurrKey.GetLength();				// check that the prefix matches				if (prefixLen == 0 || strActivePrefix == strCurrKey.Left( prefixLen ))				{					// check that this is not a key for a deeper subpref (if it is,					// there will be another separator in the key string)										strCurrKeyAfterPrefix = strCurrKey.Right(keyLen - prefixLen);										if (bReturnDeeperNestings ||						-1 == strCurrKeyAfterPrefix.Find(kPrefPrefixSeparator) )					{						if (nCountDown > 0)						{							nCountDown--;						}						else						{							// this is the one to return							outStrKey = (const char*) strCurrKeyAfterPrefix;							res = HXR_OK;														// no need to look at others							break;						}					}				}			}		}				CFRelease(cfArray);	}	return res;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -