
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5024 8e941d3f-bd1b-0410-a28a-d453659cc2b4
177 lines
4.9 KiB
ObjectPascal
177 lines
4.9 KiB
ObjectPascal
unit PropListUtil;
|
|
|
|
{
|
|
|
|
Class for working with property list (for example, app bundle's
|
|
Info.plist).
|
|
|
|
Author: Phil Hess.
|
|
Copyright: Copyright (C) 2010 Phil Hess. All rights reserved.
|
|
License: Modified LGPL. This means you can link your code to this
|
|
compiled unit (statically in a standalone executable or
|
|
dynamically in a library) without releasing your code. Only
|
|
changes to this unit need to be made publicly available.
|
|
|
|
}
|
|
|
|
{$MODE Delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
MacOSAll,
|
|
CFHelpers; {Handy routines for use with Core Foundation}
|
|
|
|
type {Note: Not all CF object types are supported yet by this class}
|
|
TCFPropertyList = class(TObject)
|
|
private
|
|
propertyList : CFPropertyListRef;
|
|
function GetValue(const KeyName : string) : UnivPtr;
|
|
public
|
|
destructor Destroy; override;
|
|
function LoadFromFile(const FileName : string) : Boolean;
|
|
function GetString(const KeyName : string) : string;
|
|
function GetBoolean(const KeyName : string) : Boolean;
|
|
end;
|
|
|
|
function GetInfoPlistString(const KeyName : string) : string;
|
|
|
|
|
|
implementation
|
|
|
|
destructor TCFPropertyList.Destroy;
|
|
begin
|
|
FreeCFRef(propertyList);
|
|
end;
|
|
|
|
|
|
function TCFPropertyList.LoadFromFile(const FileName : string) : Boolean;
|
|
{Adapted from example ObjC code given here:
|
|
http://developer.apple.com/library/mac/documentation/Cocoa/
|
|
Conceptual/PropertyLists/SerializePlist/SerializePlist.html#//
|
|
apple_ref/doc/uid/10000048i-CH7-SW5}
|
|
var
|
|
plistFileName : CFStringRef;
|
|
fileURL : CFURLRef;
|
|
resourceData : CFDataRef;
|
|
errorCode : SInt32;
|
|
errorString : CFStringRef;
|
|
begin
|
|
Result := False;
|
|
|
|
FreeAndNilCFRef(propertyList); {In case something previously loaded}
|
|
|
|
AnsiStrToCFStr(FileName, plistFileName);
|
|
|
|
fileURL := CFURLCreateWithFileSystemPath(
|
|
kCFAllocatorDefault,
|
|
plistFileName,
|
|
kCFURLPOSIXPathStyle, {Interpret as POSIX path}
|
|
False); {Not a directory}
|
|
{Note that if file name is not absolute, treated relative
|
|
to working directory.}
|
|
|
|
FreeCFRef(plistFileName);
|
|
|
|
{Read the XML file.
|
|
Note getting resource data, not specified properties.}
|
|
try
|
|
if not CFURLCreateDataAndPropertiesFromResource(
|
|
kCFAllocatorDefault,
|
|
fileURL,
|
|
@resourceData, {Place to put XML file's data}
|
|
nil,
|
|
nil,
|
|
errorCode) then
|
|
Exit;
|
|
{Description of function suggests resourceData might
|
|
be non-null even if failure, so release below.}
|
|
|
|
{Reconstitute the dictionary using the XML data.}
|
|
propertyList := CFPropertyListCreateFromXMLData(
|
|
kCFAllocatorDefault,
|
|
resourceData,
|
|
kCFPropertyListImmutable,
|
|
@errorString);
|
|
|
|
if Assigned(propertyList) then
|
|
Result := True
|
|
else
|
|
FreeCFRef(errorString); //return this too?
|
|
finally
|
|
FreeCFRef(fileURL);
|
|
FreeCFRef(resourceData);
|
|
end;
|
|
end; {TCFPropertyList.LoadFromFile}
|
|
|
|
|
|
function TCFPropertyList.GetValue(const KeyName : string) : UnivPtr;
|
|
{Retrieve key's CF value from property list.}
|
|
var
|
|
KeyRef : CFStringRef;
|
|
begin
|
|
Result := nil;
|
|
if not Assigned(propertyList) then {Error - list not loaded?}
|
|
Exit;
|
|
if CFGetTypeID(propertyList) <> CFDictionaryGetTypeID then {Not valid?}
|
|
Exit;
|
|
AnsiStrToCFStr(KeyName, KeyRef);
|
|
Result := CFDictionaryGetValue(propertyList, KeyRef);
|
|
FreeCFRef(KeyRef);
|
|
end;
|
|
|
|
|
|
function TCFPropertyList.GetString(const KeyName : string) : string;
|
|
{Retrieve key's string value from property list.}
|
|
var
|
|
Value : UnivPtr;
|
|
begin
|
|
Result := '';
|
|
Value := GetValue(KeyName);
|
|
if not Assigned(Value) then {Key not found?}
|
|
Exit;
|
|
if CFGetTypeID(Value) = CFStringGetTypeID then {Value is a string?}
|
|
Result := CFStrToAnsiStr(Value, kCFStringEncodingUTF8); //will always be UTF8
|
|
end;
|
|
|
|
|
|
function TCFPropertyList.GetBoolean(const KeyName : string) : Boolean;
|
|
{Retrieve key's Boolean value from property list.}
|
|
var
|
|
Value : UnivPtr;
|
|
begin
|
|
Result := False;
|
|
Value := GetValue(KeyName);
|
|
if not Assigned(Value) then {Key not found?}
|
|
Exit;
|
|
if CFGetTypeID(Value) = CFBooleanGetTypeID then {Value is a Boolean?}
|
|
Result := CFBooleanGetValue(Value);
|
|
end;
|
|
|
|
|
|
|
|
function GetInfoPlistString(const KeyName : string) : string;
|
|
{Retrieve key's string value from app bundle's Info.plist file.}
|
|
var
|
|
BundleRef : CFBundleRef;
|
|
KeyRef : CFStringRef;
|
|
ValueRef : CFTypeRef;
|
|
begin
|
|
Result := '';
|
|
BundleRef := CFBundleGetMainBundle;
|
|
if BundleRef = nil then {Executable not in an app bundle?}
|
|
Exit;
|
|
AnsiStrToCFStr(KeyName, KeyRef);
|
|
try
|
|
ValueRef := CFBundleGetValueForInfoDictionaryKey(BundleRef, KeyRef);
|
|
if CFGetTypeID(ValueRef) <> CFStringGetTypeID then {Value not a string?}
|
|
Exit;
|
|
Result := CFStrToAnsiStr(ValueRef, kCFStringEncodingUTF8); //will always be UTF8
|
|
finally
|
|
FreeCFRef(KeyRef);
|
|
end;
|
|
end; {GetInfoPlistString}
|
|
|
|
|
|
end.
|