46 #include "CASettingsStorage.h"
49 #include "CAAutoDisposer.h"
51 #include "CACFDistributedNotification.h"
52 #include "CACFNumber.h"
56 #include <sys/fcntl.h>
62 CASettingsStorage::CASettingsStorage(
const char* inSettingsFilePath, mode_t inSettingsFileAccessMode)
64 size_t theLength = strlen(inSettingsFilePath);
65 mSettingsFilePath =
new char[theLength + 2];
66 strlcpy(mSettingsFilePath, inSettingsFilePath, theLength + 2);
68 mSettingsFileAccessMode = inSettingsFileAccessMode;
70 mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
72 mSettingsCacheTime.tv_sec = 0;
73 mSettingsCacheTime.tv_nsec = 0;
75 mSettingsCacheForceRefresh =
true;
78 CASettingsStorage::~CASettingsStorage()
80 delete[] mSettingsFilePath;
82 if(mSettingsCache != NULL)
84 CFRelease(mSettingsCache);
88 void CASettingsStorage::CopyBoolValue(CFStringRef inKey,
bool& outValue,
bool inDefaultValue)
const
91 outValue = inDefaultValue;
94 CFTypeRef theValue = NULL;
95 CopyCFTypeValue(inKey, theValue, NULL);
101 if(CFGetTypeID(theValue) == CFBooleanGetTypeID())
104 outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
106 else if(CFGetTypeID(theValue) == CFNumberGetTypeID())
109 SInt32 theNumericValue = 0;
110 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
113 outValue = theNumericValue != 0;
121 void CASettingsStorage::CopySInt32Value(CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue)
const
124 outValue = inDefaultValue;
127 CFTypeRef theValue = NULL;
128 CopyCFTypeValue(inKey, theValue, NULL);
134 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
137 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
145 void CASettingsStorage::CopyUInt32Value(CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue)
const
148 outValue = inDefaultValue;
151 CFTypeRef theValue = NULL;
152 CopyCFTypeValue(inKey, theValue, NULL);
158 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
161 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
169 void CASettingsStorage::CopySInt64Value(CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue)
const
172 outValue = inDefaultValue;
175 CFTypeRef theValue = NULL;
176 CopyCFTypeValue(inKey, theValue, NULL);
182 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
185 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
193 void CASettingsStorage::CopyUInt64Value(CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue)
const
196 outValue = inDefaultValue;
199 CFTypeRef theValue = NULL;
200 CopyCFTypeValue(inKey, theValue, NULL);
206 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
209 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
217 void CASettingsStorage::CopyFloat32Value(CFStringRef inKey, Float32& outValue, Float32 inDefaultValue)
const
220 outValue = inDefaultValue;
223 CFTypeRef theValue = NULL;
224 CopyCFTypeValue(inKey, theValue, NULL);
230 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
233 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
241 void CASettingsStorage::CopyFloat64Value(CFStringRef inKey, Float64& outValue, Float64 inDefaultValue)
const
244 outValue = inDefaultValue;
247 CFTypeRef theValue = NULL;
248 CopyCFTypeValue(inKey, theValue, NULL);
254 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
257 CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
265 void CASettingsStorage::CopyNumberValue(CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue)
const
271 CFTypeRef theValue = NULL;
272 CopyCFTypeValue(inKey, theValue, inDefaultValue);
278 if(CFGetTypeID(theValue) == CFNumberGetTypeID())
281 outValue =
static_cast<CFNumberRef
>(theValue);
289 outValue = inDefaultValue;
297 void CASettingsStorage::CopyStringValue(CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue)
const
303 CFTypeRef theValue = NULL;
304 CopyCFTypeValue(inKey, theValue, inDefaultValue);
310 if(CFGetTypeID(theValue) == CFStringGetTypeID())
313 outValue =
static_cast<CFStringRef
>(theValue);
321 outValue = inDefaultValue;
329 void CASettingsStorage::CopyArrayValue(CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue)
const
335 CFTypeRef theValue = NULL;
336 CopyCFTypeValue(inKey, theValue, inDefaultValue);
342 if(CFGetTypeID(theValue) == CFArrayGetTypeID())
345 outValue =
static_cast<CFArrayRef
>(theValue);
353 outValue = inDefaultValue;
361 void CASettingsStorage::CopyDictionaryValue(CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue)
const
367 CFTypeRef theValue = NULL;
368 CopyCFTypeValue(inKey, theValue, inDefaultValue);
374 if(CFGetTypeID(theValue) == CFDictionaryGetTypeID())
377 outValue =
static_cast<CFDictionaryRef
>(theValue);
385 outValue = inDefaultValue;
393 void CASettingsStorage::CopyDataValue(CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue)
const
399 CFTypeRef theValue = NULL;
400 CopyCFTypeValue(inKey, theValue, inDefaultValue);
406 if(CFGetTypeID(theValue) == CFDataGetTypeID())
409 outValue =
static_cast<CFDataRef
>(theValue);
417 outValue = inDefaultValue;
425 void CASettingsStorage::CopyCFTypeValue(CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue)
const
428 const_cast<CASettingsStorage*
>(
this)->RefreshSettings();
431 if(!CFDictionaryGetValueIfPresent(mSettingsCache, inKey, &outValue))
434 outValue = inDefaultValue;
444 void CASettingsStorage::SetSInt32Value(CFStringRef inKey, SInt32 inValue)
446 CACFNumber theValue(inValue);
447 SetCFTypeValue(inKey, theValue.GetCFNumber());
450 void CASettingsStorage::SetUInt32Value(CFStringRef inKey, UInt32 inValue)
452 CACFNumber theValue(inValue);
453 SetCFTypeValue(inKey, theValue.GetCFNumber());
456 void CASettingsStorage::SetSInt64Value(CFStringRef inKey, SInt64 inValue)
458 CACFNumber theValue(inValue);
459 SetCFTypeValue(inKey, theValue.GetCFNumber());
462 void CASettingsStorage::SetUInt64Value(CFStringRef inKey, UInt64 inValue)
464 CACFNumber theValue(inValue);
465 SetCFTypeValue(inKey, theValue.GetCFNumber());
468 void CASettingsStorage::SetFloat32Value(CFStringRef inKey, Float32 inValue)
470 CACFNumber theValue(inValue);
471 SetCFTypeValue(inKey, theValue.GetCFNumber());
474 void CASettingsStorage::SetFloat64Value(CFStringRef inKey, Float64 inValue)
476 CACFNumber theValue(inValue);
477 SetCFTypeValue(inKey, theValue.GetCFNumber());
480 void CASettingsStorage::SetNumberValue(CFStringRef inKey, CFNumberRef inValue)
482 SetCFTypeValue(inKey, inValue);
485 void CASettingsStorage::SetStringValue(CFStringRef inKey, CFStringRef inValue)
487 SetCFTypeValue(inKey, inValue);
490 void CASettingsStorage::SetArrayValue(CFStringRef inKey, CFArrayRef inValue)
492 SetCFTypeValue(inKey, inValue);
495 void CASettingsStorage::SetDictionaryValue(CFStringRef inKey, CFDictionaryRef inValue)
497 SetCFTypeValue(inKey, inValue);
500 void CASettingsStorage::SetDataValue(CFStringRef inKey, CFDataRef inValue)
502 SetCFTypeValue(inKey, inValue);
505 void CASettingsStorage::SetCFTypeValue(CFStringRef inKey, CFTypeRef inValue)
511 CFDictionarySetValue(mSettingsCache, inKey, inValue);
517 void CASettingsStorage::RemoveValue(CFStringRef inKey)
523 CFDictionaryRemoveValue(mSettingsCache, inKey);
529 void CASettingsStorage::RemoveAllValues()
535 CFDictionaryRemoveAllValues(mSettingsCache);
541 void CASettingsStorage::SendNotification(CFStringRef inName, CFDictionaryRef inData,
bool inPostToAllSessions)
const
543 CACFDistributedNotification::PostNotification(inName, inData, inPostToAllSessions);
546 void CASettingsStorage::ForceRefresh()
548 mSettingsCacheForceRefresh =
true;
551 inline bool operator<(
const struct timespec& inX,
const struct timespec& inY)
553 return ((inX.tv_sec < inY.tv_sec) || ((inX.tv_sec == inY.tv_sec) && (inX.tv_nsec < inY.tv_nsec)));
556 void CASettingsStorage::RefreshSettings()
560 struct stat theFileInfo;
561 int theStatError = stat(mSettingsFilePath, &theFileInfo);
564 bool theSettingsWereCached =
false;
566 if(theStatError == 0)
569 if((mSettingsCache == NULL) || (mSettingsCacheTime < theFileInfo.st_mtimespec) || mSettingsCacheForceRefresh)
572 FILE* theFile = fopen(mSettingsFilePath,
"r");
576 int theError = flock(fileno(theFile), LOCK_EX);
580 fseek(theFile, 0, SEEK_END);
581 size_t theFileLength = ftell(theFile);
582 fseek(theFile, 0, SEEK_SET);
584 if(theFileLength > 0)
587 CAAutoFree<Byte> theRawFileData(theFileLength);
590 fread(static_cast<Byte*>(theRawFileData), theFileLength, 1, theFile);
593 flock(fileno(theFile), LOCK_UN);
596 CACFData theRawFileDataCFData(static_cast<Byte*>(theRawFileData), static_cast<UInt32>(theFileLength));
599 if(mSettingsCache != NULL)
601 CFRelease(mSettingsCache);
602 mSettingsCache = NULL;
606 mSettingsCache = (CFMutableDictionaryRef)CFPropertyListCreateFromXMLData(NULL, theRawFileDataCFData.GetCFData(), kCFPropertyListMutableContainersAndLeaves, NULL);
609 mSettingsCacheTime = theFileInfo.st_mtimespec;
612 theSettingsWereCached =
true;
618 mSettingsCacheForceRefresh =
false;
623 if((theStatError != 0) || (!theSettingsWereCached && (theFileInfo.st_mtimespec < mSettingsCacheTime)))
627 if(mSettingsCache != NULL)
629 CFRelease(mSettingsCache);
630 mSettingsCache = NULL;
632 mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
634 mSettingsCacheTime.tv_sec = 0;
635 mSettingsCacheTime.tv_nsec = 0;
639 void CASettingsStorage::SaveSettings()
641 if(mSettingsCache != NULL)
644 CACFData theNewRawPrefsCFData(CFPropertyListCreateXMLData(NULL, (CFPropertyListRef)mSettingsCache),
true);
647 FILE* theFile = fopen(mSettingsFilePath,
"w+");
651 int theError = flock(fileno(theFile), LOCK_EX);
655 if(mSettingsFileAccessMode != 0)
657 fchmod(fileno(theFile), mSettingsFileAccessMode);
661 fwrite(theNewRawPrefsCFData.GetDataPtr(), theNewRawPrefsCFData.GetSize(), 1, theFile);
667 flock(fileno(theFile), LOCK_UN);
673 struct stat theFileInfo;
674 stat(mSettingsFilePath, &theFileInfo);
677 mSettingsCacheTime = theFileInfo.st_mtimespec;