//************************************************************************************** // Filename: CFDataArray.cp // Part of Contextual Menu Workshop by Abracode Inc. // http://free.abracode.com/cmworkshop/ // Copyright © 2002-2003 Abracode, Inc. All rights reserved. // // Description: CFArray-based list of items // Design goals: // - not to throw // - load and save data to preferences file via CFPreferences // - the object does own the array and deletes it // - list is unsorted // - duplicates are not eliminated // //************************************************************************************** // Revision History: // Monday, August 19, 2002 - Original //************************************************************************************** #include "CFDataArray.h" #include "CFObjDel.h" CFDataArray::CFDataArray(void) { mArray = ::CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); //mArray may return NULL, we do not throw, //but all functions in this class must be prepared for NULL and check for it } CFDataArray::CFDataArray(CFStringRef inKey, CFStringRef inPrefsIdentifier) : mArray(NULL) { LoadArrayFromPrefs(inKey, inPrefsIdentifier); } CFDataArray::~CFDataArray(void) { if(mArray != NULL) { ::CFRelease(mArray); mArray = NULL; } } CFIndex CFDataArray::GetCount() const { if(mArray == NULL) return 0; return ::CFArrayGetCount(mArray); } void CFDataArray::AddItem(const void *inData, CFIndex inSize) { if( (mArray == NULL) || (inData == NULL) ) return; //add item CFDataRef theDataRef = ::CFDataCreate( kCFAllocatorDefault, (const UInt8 *)inData, inSize ); if(theDataRef != NULL) { ::CFArrayAppendValue( mArray, (const void *)theDataRef ); } } //zero-based index void CFDataArray::RemoveItemAt(CFIndex inIndex) { if(mArray == NULL) return; ::CFArrayRemoveValueAtIndex( mArray, inIndex ); } void CFDataArray::RemoveAllItems() { if(mArray == NULL) return; ::CFArrayRemoveAllValues(mArray); } //index is zero-based //returns true if valid data is set, false otherwise //ioBuffSize returns actual len of data. //if supplied buffer is too small only a fraction of data is put there Boolean CFDataArray::FetchItemAt(CFIndex inIndex, void *ioItemBuff, CFIndex &ioBuffSize) const { if( (mArray == NULL) || (ioItemBuff == NULL) ) return false; CFIndex theCount = ::CFArrayGetCount(mArray); if( (inIndex >= 0) && (inIndex < theCount) ) { CFTypeRef theItem = ::CFArrayGetValueAtIndex( mArray, inIndex); if( (theItem != NULL) && (::CFGetTypeID(theItem) == ::CFDataGetTypeID()) ) { CFDataRef dataRef = (CFDataRef)theItem; CFIndex theLen = ::CFDataGetLength(dataRef); if(theLen > ioBuffSize) {//cannot fit in user-supplied buffer //fit what we can, then inform outside world that buffer sizes do not agree CFIndex temp = theLen; theLen = ioBuffSize; ioBuffSize = temp; } else ioBuffSize = theLen;//the len is less or equal then buffer size const UInt8 * dataPtr = ::CFDataGetBytePtr(dataRef); if(dataPtr != NULL) { ::BlockMoveData(dataPtr, ioItemBuff, theLen); return true; } } } return false; } //you may need to call CFPreferencesAppSynchronize before calling this function void CFDataArray::LoadArrayFromPrefs(CFStringRef inKey, CFStringRef inPrefsIdentifier) { if(mArray != NULL) { ::CFRelease(mArray); mArray = NULL; } if( (inKey == NULL) || (inPrefsIdentifier == NULL) ) { mArray = ::CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); return; } CFPropertyListRef resultRef = ::CFPreferencesCopyAppValue( inKey, inPrefsIdentifier ); if(resultRef != NULL) { CFObjDel refDel(resultRef); if( ::CFGetTypeID(resultRef) == ::CFArrayGetTypeID() ) {//we need a mutable copy of this array mArray = ::CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)resultRef); } } else {//unable to read or not created yet mArray = ::CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); } } //you may need to call CFPreferencesAppSynchronize after calling this function void CFDataArray::SaveArrayToPrefs(CFStringRef inKey, CFStringRef inPrefsIdentifier) const { if(mArray == NULL) return; ::CFPreferencesSetAppValue( inKey, (CFPropertyListRef)mArray, inPrefsIdentifier ); }